Java类的生命周期

161 阅读3分钟

简介

    介绍Java类的生命周期

类的生命周期

    一个类的生命周期大致如下图:

  • 1.加载:查找字节流,并且根据此创建类
  • 2.链接:将创建的类合并到Java虚拟机中,使之能够执行
    • 1.验证:是否满足约束条件
    • 2.准备:为被加载类的静态字段分配内存;创建符合引用
    • 3.解析:将符合引用解析成实际引用;如果符号引用指向一个未被加载的类的字段或方法,将触发这个类的加载(未必触发链接和初始化)
  • 3.初始化:为标记为常量的字段赋值,以及执行方法
  • 4.使用
  • 6.卸载

    如上所示,类的生命周期可分为5大步

    其中第一步加载过程中还涉及到类加载器,这部分也是重要的知识点,但这里不进行探讨,专门用其他一篇文章进行探讨

初始化时的静态赋值

    第三步初始化还挺重要,其中涉及到了静态代码和字段运行的问题,在初始化阶段,静态赋值有下面两种情况:

    1.如果是基本类型或者字符串,并且被final修饰,那么就标记成常量值,并且直接由Java虚拟机进行初始化

    2.其他的复制操作以及静态代码块,会被置于同一个方法中,并将其命名为,并通过加锁确保仅被执行一次

初始化的触发

    大致有下面的情况:主、new、两静态、子、default、发射、methodHandler

  • 1.当虚拟机启动时,初始化用户指定的主类
  • 2.当遇到用以新建目标类实例的 new 指令时,初始化 new 指令的目标类
  • 3.当遇到调用静态方法的指令时,初始化该静态方法所在的类
  • 4.当遇到访问静态字段的指令时,初始化该静态字段所在的类
  • 5.子类的初始化会触发父类的初始化
  • 6.如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化
  • 7.使用反射 API 对某个类进行反射调用时,初始化这个类
  • 8.当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类
不会初始化(可能会被加载)

    有如下情况:

    1. 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化
    1. 定义对象数组,不会触发该类的初始化
    1. 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类
    1. 通过类名获取 Class 对象,不会触发类的初始化,Hello.class 不会让 Hello 类初始化
    1. 通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。Class.forName(“jvm.Hello”)默认会加载 Hello 类
    1. 通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作(加载了,但是不初始化)

总结

    介绍了类的生命周期,及初始化步骤中需要了解的相关知识