美文网首页
深入理解JAVA虚拟机6-虚拟机类加载机制

深入理解JAVA虚拟机6-虚拟机类加载机制

作者: 半夏丨微凉丶 | 来源:发表于2019-11-08 14:13 被阅读0次

类加载时机

类的生命周期:加载,验证,准备、解析、初始化、使用、卸载

  1. 遇到new getstatic putstatic invokestatic这4条字节码指令时,如果没有初始化,必须先触发初始化
  2. 对类进行反射调用的时候,要先初始化
  3. 初始化一个类时,如果父类还没有初始化,先初始化父类
  4. 虚拟机启动时,用户需要指定一个主类,虚拟机会先初始化这个主类
  5. 如果一个java.lang.invoke.MethodHandle实例最后的解析结果是REF_getStatic,REF_putStatic,REF_invokeStatic时,并且这个方法对于的类没有初始化,需要先触发初始化。
    以上5 种场景为主动引用,初次之后,所有引用类的方法都不会初始化,称为被动引用。
    子类引用服父类的静态字段不会触发子类初始化。对于静态字段,只有直接定义这个字段的类才会初始化
    通过数组定义类,不会触发类的初始化,如下的定义不会触发SuperClass的初始化
SuperClass[] s = new SuperClass[10];

定义在类中的常量不会触发类的初始化。如被final修饰的常量。因为在编译阶段将此值转储到常量池了

类加载过程

加载->验证->准备->解析->初始化

加载

加载阶段完成以下三件事情:
通过一个类的全限定名来获取定义此类的二进制字节流
将这个字节流所代表的的静态存储结构转为方法区的运行时数据结构
在内存中生成一个CLASS对象,作为方法区这个类的各种数据的访问入口

验证

确保class文件字节流中包含的信息符合当前虚拟机的要求,不会危害虚拟机自身的安全。

  1. 文件格式验证: 验证字节流符合class文件格式规范
    检查是否以魔数(magic)0xCAFEBABE开头
    检查minor version 和major version是否在当前虚拟的处理范围之内
    .....

  2. 元数据验证:保证字节码描述的信息符合java语言规范
    这个类是否有父类
    这个类是否继承了不能被继承的类
    这个类是否实现了父类或者接口中的方法
    ...

  3. 字节码验证:通过控制流和数据流分析确定程序语义是合法的、符合罗的。

  4. 符号引用验证
    符号引用中通过字符串描述的全限定名是否能找到对应的类。

准备

准备阶段是正式为类变量(被static修饰的变量)分配内存并设置类初始值(如果没有final修饰,则将值设置为0值,如果被final修饰,则在此阶段将值直接赋给变量)的阶段,这些值都在方法区中被分配。

解析

将虚拟机常量池中的符号引用转为直接引用的过程。

初始化:执行类构造器的过程

类加载器

用于加载二进制字节流,在类加载阶段使用,虚拟机外部实现。

双亲委派模型

  1. 启动类加载 bootstrap classloader
    加载<JAVA_HOME>\lib下的,并且被虚拟机识别的类
  2. 扩展类加载器 extension classloader
    加载<JAVA_HOME>\lib\ext目录中的类
    3.应用程序类加载器 application classloader
    负责加载用户路径上指定的类库
  3. 自定义加载器


    类加载器双亲委派模型.png

如果一个类收到类加载的请求,不会先自己加载类,而是委派给父类加载器去加载,每一层次的加载都是如此,因此所有的类加载请求到会集中的启动类加载器中,只有当父加载器无法加载时,子加载器才会自己加载。
双亲委派模型保证只会加载一个同名的类

相关文章

网友评论

      本文标题:深入理解JAVA虚拟机6-虚拟机类加载机制

      本文链接:https://www.haomeiwen.com/subject/gzmvbctx.html