类的加载过程包括以下5个阶段:
加载、验证、准备、解析、初始化
这几个阶段是顺序开始,但不一定是顺序进行或完成的,通常各阶段相互交叉混合进行
加载
将外部的二进制流class文件存储到方法区,并在java堆中创建一个java.lang.Class类的对象,作为方法区的访问入口
验证
目的是确保被加载的类的正确性,验证内容包括
(1)文件格式验证:如是否以oxCAFEBABE开头,版本号是否在虚拟机支持范围内,常量池中的类型是否都支持
(2)元数据验证:这个类是否有父类
(3)字节码验证
(4)符号引用验证
验证极端很重要但不是必须的,可以通过-Xverifynone关闭大部分的类验证
准备
在方法区中为类的静态变量分配内存,初始化为各种类型对应的默认值(如数字型为0,对象为null,bool类型为false),此时并不会将程序中设置的值初始化给变量(是在后面的初始化阶段进行的),但有一种情况“静态常量类型”会直接赋值为程序中指定的值,如: public static final int a=6
解析
把常量池中的符号引用直接替换为直接引用
初始化
为类的静态变量初始化,初始化步骤为:
(1)如果该类还没有被加载和连接,则先进行加载和连接
(2)如果该类的直接父类还没有初始化,则先初始化其父类
(3)如果类中有初始化语句,则依次执行这些初始化语句
类的初始化时机包括:
(1)使用new 创建类的实例
(2)访问某个类的静态变量
(3)调用类的静态方法
(4)反射
(5)初始化该类的子类