JVM之类加载机制
文章目录
1)概述
2)类加载的过程
3)类加载器和双亲委派模型
概述
- 虚拟机从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可被虚拟机直接使用的Java类型的过程
- 类加载的时机
- 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:
类加载的过程
- 加载
- 通过类的全限定名来获取定义类的二进制字节流。
- 将该二进制字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的
java.lang.Class
对象
- 验证
- 为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
- 可用
-Xverify:none
来关闭大部分的类验证措施,以缩短虚拟机类加载的时间 - 1.文件格式验证
- 保证输入的字节流能正确的解析并存储于方法区中,且格式上符合描述一个Java类型信息的要求
- 2.元数据验证
- 对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求
- 3.字节码验证
- 对类的方法体进行校验分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的事件
- 4.符号引用验证
- 对类自身以外的信息进行匹配性校验
- 准备
- 为类变量分配内存,设置类变量初始值
- 解析
- 验证,准备和解析称为连接
- 解析可能会在初始化之后再开始,它是将常量池的符号引用替换为直接引用的过程
- 初始化
- 开始执行类中定义的Java代码,执行类构造器()
- 遇到以下情况必须对类进行初始化
- 遇到
new、getstatic、putstatic或invokestatic
- 使用
java.lang.reflect
包的方法对类进行反射调用 - 当初始化一个类的时候,若发现其父类还未进行初始化,需先触发其父类的初始化;
- 在虚拟机启动时,需指定一个要执行的主类,虚拟机会先初始化它;
- 当使用JDK1.7的动态语言支持时,若一个java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,且这个方法句柄所对应的类未进行初始化,需先触发其初始化。
- 遇到
类加载器
- 类加载器
- 每个类加载器都拥有一个独立的类名称空间,它不仅用于加载类,还和这个类本身一起作为在JVM中的唯一标识。比较两个类是否相等,只要看它们是否由同一个类加载器加载。
- 启动类加载器
- 虚拟机自身的一部分
- 其他类加载器
- 独立于虚拟机外部
- 扩展类加载器
- 应用程序类加载器
- 自定义类加载器
- 双亲委派模型
- 表示类加载器之间的层次关系
- 除了顶层启动类加载器外,其余类加载器都应有自己的父类加载器,通过组合关系来复用加载器的代码
- 若一个类加载器收到了类加载的请求,它先会把这个请求委派给父类加载器,并向上传递,最终请求都传送到顶层的启动类加载器中。只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。
参考
《深入理解Java虚拟机》
理解JVM之类加载机制