乐趣区

关于java:27-类的生命周期

  1. 加载

    1. 通过全类名获取此类的二进制字节流
    2. 将字节流所代表的动态存储构造转换成办法区的运行时数据结构
    3. 在内存中生成一个 class 对象,作为办法区这些数据的拜访入口

    数组类型是由 java 虚拟机间接创立的,不是通过类加载器创立的。
    非数组类型能够通过自定义类加载器实现加载。(重写 loadclass 办法)

  2. 连贯

    加载阶段未完结,连贯阶段可能曾经开始了。

    • 验证

      • 文件格式验证
        验证字节流是否合乎 class 文件格式标准

        • 是否以 0xCAFEBABE 结尾
        • 主次版本号是否在以后虚拟机解决范畴之内
        • 常量池中的常量是否有不被反对的类型
      • 元数据验证
        对字节码的信息进行语义剖析,保障形容的信息合乎 java
        语言标准

        • 类是否有父类
        • 是否继承了不能被继承的类(被 final 润饰的类)
      • 字节码验证

        • 验证程序语义非法
      • 符号援用验证
    • 筹备

      为类变量(即动态变量)分配内存并设置变量初始值。
      在 1.7 前放在永恒代办法区,1.7 后字符串常量池、动态变量挪动到堆中。
      这里的初始值是数据类型对应的 0 值。如果被 final 润饰了,则被赋值为理论值。

    • 解析

      将常量池内的“符号援用”替换为“间接援用”。
      针对类、接口、类办法、接口办法、办法类型、办法句柄、和调用限定符。
      间接援用是指向指标的指针、绝对偏移量或可间接定位到指标的句柄。每个类有一张办法表寄存类中所有办法,只有晓得某办法在表中偏移量就能够间接调用。

  3. 初始化

    这一步 jvm 开始真正执行类中定义的 java 程序代码。
    执行 <clinit> 办法,带锁线程平安,可能引起阻塞。
    以下五种状况,必须对类进行初始化

    • new、getstatic、putstatic、invokestatic 指令,别离是创立实例、拜访动态变量、给动态变量赋值、调用类静态方法。
    • 应用 java.lang.reflect 包对类进行反射调用时,例如 class.forname(“”),newInstance()
    • 初始化类时,如果父类没初始化,要先初始化父类
    • 虚拟机启动时,会先初始化 main 办法所在的类
    • 要应用轻量级的反射调用 methodHandle、VarHandle,必须先应用 findStaticVarHandle 初始化类
    • 如果接口定义了 jdk8 新退出的默认办法(被 default 润饰的办法),初始化这个接口的实现类之前要先初始化接口。
  4. 应用

  5. 卸载

    卸载即 class 对象被 gc,须要满足三个要求

    1. 所有实例对象都被 gc 了。
    2. 类没有被任何中央援用。
    3. 类加载器实例被 gc。
      由 jvm 自带的类加载器加载的类是不会被卸载的,由咱们自定义的类加载器加载的类是可能被卸载的。
退出移动版