JVM类加载机制

来自随意问技术百科
跳转至: 导航搜索

类加载时机

  1. 遇到new, getstatic, putstatic 或 invokestatic 这4挑字节码指令;
  2. 使用 java.lang.reflect 包的方法对类进行反射调用;
  3. 初始化一个类的时候,其父类还没有初始化,必须先触发其父类的初始化;(对于接口,只有在真正用到其父接口的时候才会初始化)
  4. 虚拟机启动时,用户指定要执行的主类
  5. 当使用 JDK 1.7 的动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后的解析结果 REF_getStatic, REF_putStatic, REF_invokeStatic 的方法句柄,并且这个方法句柄锁对应的类没有进行出事,则需要先触发其初始化

类加载过程

  1. 加载
    1. 通过一个类的全限定名来获取定义此类的二进制字节流;
    2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
    3. 在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口。
  2. 连接
    1. 验证:文件格式验证、元数据验证、字节码验证、符号引用验证。
    2. 准备:为类变量分配内存并设置类变量初始值。(对应属性表中的ConstantValue,final static修饰,非final static修饰的变量初始值为0)
    3. 解析:将常量池内的符号引用转换为直接引用的过程。
  3. 初始化:初始化阶段是类加载的最后一步,到此阶段才真正开始执行类定义中的java程序代码(执行类构造器 <clinit>() 方法)。
    • <clinit>() 方法是由编译器自动收集类中所有的类变量的赋值动作和静态语句块( static{})中的语句合并产生,收集的顺序由语句在源文件中出现的顺序决定,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,可以赋值,但不能访问。
  4. 使用
  5. 卸载

类加载器(ClassLoader)

  • 启动类加载器(Bootstrap ClassLoader):负责加载存放在 <JAVA_HOME>\lib 目录中的,或者被 -Xbootclasspath 参数所指定的路径中的,且是虚拟机识别的(仅安装文件名识别,如 rt.jar)类库。
  • 扩展类加载器(Extension ClassLoader):负责加载 <JAVA_HOME>\lib\ext 目录中下、或者被 java.ext.dirs 系统变量制定的路径下的所有类库。
  • 应用程序类加载器(Application ClassLoader):这个类加载器也称为系统类加载器,负责加载用户类路径上所指定的类库。