1 开门见山看一道面试题:
答案有点意外吧 我们分析下:
2 类从被加载到虚拟机内存开始,直到卸载出内存为止,它的整个生命周期包括了:加载,验证,准备,解析 初始化 ,使用 ,卸载。其中验证,准备和解析三个部分统称为链接。
3 何时开始类的初始化
什么情况下需要开始类加载过程的第一个阶段"加载"。以下几种情况,如果类未初始化会对类进行初始化。
创建类的实例
访问类的静态变量
访问类的静态方法
反射如(Class.forName("com.exaple.aaa.Test"))
当初始化一个类时,发现其父类还未初始化,则先进行父类的初始化。
4 类的加载过程
加载阶段是类加载过程的第一个阶段,在此阶段,虚拟机需要完成以下三件事情:
1 通过一个类的全限定名来获取定义此类的二进制字节流。
2 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3 在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。
5 验证阶段
验证阶段是链接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的虚拟机符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
包括:文件格式验证,元数据验证,字节码验证,符号引用验证。
6 准备阶段
是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配,准备阶段不分配类中的实例变量的内存,实例变量将在对象实例化时随对象一起分配在java堆中。
public static final int value=123;
在准备阶段value初始化值为0,在初始化阶段才会变成123。
7 解析阶段
是虚拟机将常量池内的符号引用替换成直接引用的过程。
8 初始化
类初始化是类加载的最后一步,才开始执行类中定义的JAVA程序代码。
初始化阶段是执行类构造器<clinit>()方法的过程,方法是由编译器自动收集类中的所有变量的赋值动作和静态语句块中的语句合并产生的。
我们看上面代码进行分析:
1 SingleTon singleTon = SingleTon.getInstance();调用了类的静态方法,触发了类的初始化
2 类加载的时候在准备过程中为类的静态变量分配内存并初始化默认值
singleTon=null ,count1=0,count2=0
3 类初始化,为类的静态变量赋值和执行静态代码块,singleTon赋值为new SingleTon().调用类的构造方法。
4 执行完new SingleTon()后count1=0 count2=1
5 继续为count1 , count2赋值,此时count1没有赋值 count2赋值为0所以结果如开篇截图。
附录:
对象在class文件加载完毕,以及为格成员方法区开辟好内存空间之后,就开始初始化操作:
1 基类静态代码块,基类静态成员字段(并列优先级,按代码中出现先后顺序) 只有第一次加载类时执行
2 派生类静态代码块 ,派生类静态成员字段(并列优先级,按代码中出现先后顺序) 只有第一次加载类时执行
3 基类普通代码块,基类普通成员字段(并列优先级,按代码中出现先后顺序)
4 基类的构造函数
3 派生类普通代码块,派生类普通成员字段(并列优先级,按代码中出现先后顺序)
4 派生类的构造函数
网友评论