类的字节码从磁盘上进入到内存里的五个大的阶段:
-
加载:查找并加载类的二进制数据到内存,生产类的Class对象。
-
连接:
-
验证: 确保被加载的类的正确性
-
准备:为类的静态变量分配内存,并将初始化默认值(类的实例变量还没有)
-
解析:把类中的符号引用转换为直接引用
-
初始化:为类的静态变量赋予正确的初始值
-
使用(如创建类的对象,调用类的方法)
-
卸载(将驻留在内存里的类的数据结构销毁掉,卸载后不能再使用该类创建对象了)
初始化时机:
Java程序对类的使用方式可分为两种:
-
主动使用
-
被动使用
所有的Java虚拟机实现必须在每个类或接口被Java程序“首次主动使用”时才初始化他们。
主动使用(七种)
-
创建类的实例
-
访问某个类或接口的静态变量(助记符:getstatic)(但static final的常量除外,它在常量池中),或者对该静态变量赋值(助记符:putstatic)
-
调用类的静态方法(助记符:invokestatic)
-
反射(如Class.forName(“com.test.Test”))
-
初始化一个类的子类
-
Java虚拟机启动时被标明为启动类的类(即含有main()方法的类)
被动使用
- 访问静态域时,只有真正声明这个域的类才被初始化,比如:通过子类引用父类静态变量,不会引起子类初始化
- 通过数组定义类引用,类不会初始化,new一个数组只是分配了空间
- 引用常量不会使类初始化(常量在常量池)