从单例模式看JVM内幕
来源:互联网 发布:淘宝账号怎么申请注册 编辑:程序博客网 时间:2024/04/27 16:34
先看一道简单而变态的面试题:
class Singleton{
private static Singleton singleton = new Singleton(); //①
public static int counter1;
public static int counter2 = 0;
//private static Singleton singleton = new Singleton(); //②
public Singleton(){
counter1++;
counter2++;
}
public static Singleton getInstance(){
return singleton;
}
}
//测试类
public class Mytest {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println("counter1:"+singleton.counter1);
System.out.println("counter2:"+singleton.counter2);
}
}
//输出结果
private static Singleton singleton = new Singleton();语句在位置①,结果:
counter1:1
counter1:0
private static Singleton singleton = new Singleton();语句在位置②,结果:
counter1:1
counter1:1
JVM加载、连接、初始化.class文件原理如下:
/*
* 1.虚拟机的生命周期:结束的几种方式:正常结束、System.exit()、异常、操作系统错误
* 2.加载、连接、初始化
* 加载:class文件二进制加载到内存
* 连接:
* 验证:确保加载类的正确性
* 准备:为类得静态变量分配内存,并将其默认为初始值
* 解析:把类得符号引用转换为直接引用
* 初始化:为类的静态变量赋予正确的初始值
*
* java对类的使用方式2种:主动使用、被动使用
* 主动使用(6种):
* 创建类得实例:new一个实例
* 访问静态变量
* 调用类得静态方法
* 反射:Class.forName("com.xxx.xxx")
* 初始化类的子类
* java虚拟机启动时被标明为启动类得类:有main方法的入口
*
* ***所有java虚拟机实现必须在每个类或接口被java程序“首次主动使用”时才初始化它们
*
* 1.类的加载
* 加载过程:.class文件中二进制读入内存,将其放在运行时数据区的方法区,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区的数据结构
* 加载方式:本地系统加载
* 网络下载.class文件:URLClassLoader
* 从zip、jar归档文件中加载文件
* 数据库中提取.class文件
* java源文件动态编译的.class文件
* 加载器:
* java自带加载器:
* a.根类加载器:bootstrap (c++编写的,在程序中无法在java代码中获得该类)
* b.扩展加载器:extension (java写的)
* c.系统(应用)加载器:system (java写的)
* 用户自定义加载器:java.lang.ClassLoader子类
* 2.连接:将已经读入到内存的类的二进制数据合并到虚拟机运行时环境中去
* 验证:
* 类的文件结构检查:java类文件固定格式
* 语义检查:符合java类语法规范:如final类无子类
* 字节码验证:字节码流 = 操作码单字节指令流,防止人为生成.class文件
* 二进制兼容性验证:一个类的方法调用另外一个类得某一方法,但方法不存在
* 准备:为类得静态变量分配内存,并将其默认为初始值
* 解析:把类得符号引用转换为直接引用
* 例子:在Worker类gotoWork()方法会引用到Car类的run()方法
* public void gotoWork(){
* car.run(); //这段代码在Worker类的二进制代码中表示为符号引用
* }
* //在Worker类的二进制数据中,包含了一个对Car类的run()方法的符号引用,它由run()方法的全名和相关描述符组成。在解析阶段,java虚拟机会把这个符号引用替换为一个指针(c语言真正的指针),该指针指向Car类的run()方法在方法区内的内存位置,这个指针就是直接引用
* 3.初始化:为类得静态变量赋予初始值
* 静态变量赋初始值有2种途径:1.在静态变量声明处。2.在静态代码块中static{}
*/
- 从单例模式看JVM内幕
- 从cocos2d-x看设计模式::单例模式
- 从jvm的角度来看单例模式
- 从单例模式的Double-Check看指令重排
- 从自己实现Ruby单例模式揭秘Ruby模块内幕
- JVM延迟加载单例模式
- 看Spring的单例模式
- 从JVM Instructions看Java
- 从JVM Instructions看Java
- 设计模式 - - - 从单例模式谈起
- JVM内幕
- 单例模式----从零单排
- 单例模式---从职员层次谈起
- 从单例模式到Happens-Before
- 从单例模式到Happens-Before
- 由单例模式探讨JVM的内存管理机制
- 从问题看本质: 研究TCP close_wait的内幕
- 从问题看本质: 研究TCP close_wait的内幕
- CollabNetSubversionEdge-1.3.1安装与配置
- QT+Coin3d程序BUG整理
- 问题:Activity has leaked window that was originally added(以解决)
- opentaps 1.5 admin 默认密码
- group by Order by 这些sql语句多字段的理解和联想
- 从单例模式看JVM内幕
- Linux环境进程间通信(五): 共享内存(上)
- uml类图符号介绍
- hdoj 2309
- 分形fractal
- 基于对象的理解
- ORA-31623: a job is not attached to this session via the specified handle
- Linux I2C子系统分析之(一) ----- 用GPIO模拟I2C总线
- 无法打开输入文件 .obj