前几篇文档记录的是 loading,现在看看 linking,initializing;
Linking
Verfication:验证文件是否符合JVM规范;
Preparation:给静态变量赋默认值;
Resolution:是否解析,将类,方法、属性等符号引用解析为指针常量池中的各种符号引用进行解析,可以理解为一个指针;
Initializing
给静态变量赋值;
执行顺序
首先我们会接受到一个文件,再校验文件下字节码前面8位是不是 cafe baba,是则下面流程
然后把所有静态成员变量赋默认值,如果是成员变量的话,先 new 再把成员变量赋默认值
再通过这个指针指向是把值赋值给是静态变量
代码展示
class demo {
public static void main(String[] args) {
System.out.println(T.count);
}
}
class T{
// 这条在前 返回 1
public static int count = 0;
// 这条在前 返回 0 仔细想想执行顺序
public static T t = new T();
private T(){
count++;
}
}
代码解释
如果 public static int count = 0 在前面的话,我们 new 的时候肯定是会 +1
如果 public static T t = new T() 在前面的话,我们在调用的时候 count 是 0,然后又执行 count = 0,所以返回的还是 0;
指令重排问题
但是再多线程环境下,如果用一个对象,可能出现指令重排;
所以需要 volatile 字段来防止指令重排;