类的加载由JVM执行引擎来完成
早期--编译期:源代码文件*.java -> 词法分析器 -> tokens流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> JVM字节码文件*.class
晚期--运行期==执行引擎执行:JVM字节码 .class -> 机器无关优化 -> 中间代码 -> 机器相关优化 -> 中间代码 -> 寄存器分配器 -> 中间代码 -> 目标机器码生成器 -> 目标机器码
1:类的生命周期:
加载、验证、准备、解析、初始化、使用、销毁,其中验证、准备、解析统称为连接
加载、验证、准备、初始化和卸载顺序确定,过程通常互相交叉混合式进行,通常在一个阶段执行的过程中调用、激活另一个阶段;
解析在某些情况下可以在初始化之后再开始---支持Java语言的运行时绑定(也称动态绑定或晚期绑定)
虚拟机规范严格规定了有且只有五种情况必须对类进行初始化,也就是执行类加载操作,而加载、验证、准备自然需要在此之前进行
五种情况被称为主动引用----触发初始化操作(page 210), 其他的引用类方式都不会触发初始化,成为被动引用
2:类加载的全过程
-----加载、验证、准备、解析、初始化,其中验证、准备、解析过程完全由虚拟机主导和控制,类加载也可以通过自定义类加载器,初始化阶段执行程序员编写的Java程序代码(转化后的字节码)
加载:完成3件事==1)通过类的全限定名来获取定义此类的二进制字节流--字节流来源:zip包中、网络、运行时计算生成(动态代理)、其他文件(jsp)、数据库中读取(少见)
2)将这个字节流所代表的京塔存储结构转化为方法区的运行时数据结构
3)在内存(没有明确规定在堆中,而是在方法区中)中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
说明:加载阶段与连接阶段的部分内容(部分字节码文件格式的验证)一般是交叉进行的
验证:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
包括文件格式验证、元数据验证、字节码验证、符号引用验证(在解析阶段发生)
准备:准备阶段是正式为类的变量(属性)分配内存并设置类变量初始值(通常为0)的阶段,这些变量所使用的的内存都将在方法区中进行分配
解析:解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符这七类符号引用
初始化:执行程序员编写的Java程序代码(转化后的字节码),初始化变量和其他资源---执行类构造器<clinit>()方法的过程,特点和细节见 page225
3:类加载器
类加载器和类本身一同确立其在Java虚拟机中的唯一性,每个类加载器都有独立的类名称空间;
双亲委派模型:启动类加载器(Bootstrap ClassLoader)---加载<JAVA_HOME>lib目录中的,或者被-Xbootclasspath参数所指定的且被虚拟机识别的类,开发者不能直接使用
扩展类加载器(Extension ClassLoader)---加载<JAVA_HOME>libext目录中的或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可直接使用
应用程序类加载器(Application ClassLoader)---也称系统类加载器,加载用户类路径ClassPath指定的类库,开发者可直接使用,程序中默认的类加载器
破坏双亲委派模型:代码热替换、模块热部署、开放服务网关协议OSGi(Open Service Gateway Initiative)
4:虚拟机字节码执行引擎