生命周期

QQ截图20200409152757.png

一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称
为连接(Linking)。

类加载

加载

  • 通过一个类的全限定名来获取定义此类的二进制字节流。
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口(反射机制)。

类的二进制流可以从许多地方获取,比如JARWARJSP、网络等等。

验证

这一阶段的目的是确保Class文件的字节流中包含的信息符合《Java虚 拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。

  1. 文件格式验证
    验证字节流是否符合Class文件格式的规范。
  2. 元数据验证
    对字节码描述的信息进行语义分析,以保证其描述的信息符合《Java语言规范》。
  3. 字节码验证
    通过数据流分析和控制流分析,确定 程序语义是合法的、符合逻辑的。
  4. 符号引用验证
    符号引用验证可以看作是对类自身以外(常量池中的各种符号引用)的各类信息进行匹配性校验,通俗来说就是,该类是否缺少或者被禁止访问它依赖的某些外部类、方法、字段等资源。

准备

准备阶段是正式为类中定义的变量(即静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段。
只有被final修饰的变量才会在此阶段被赋予程序员指定的值,否则都被赋值为类型默认值。

解析

解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程。

符号引用即一个字符串,这个字符串包含了足够多的信息,让虚拟机可以定位到一个类或方法等。
符号引用表示这个类里引用到了目标,但是目标或许还没有被加载到虚拟机内存中。

直接引用比较好理解了,就是可以直接指向目标的指针、相对偏移量或者是一个能 间接定位到目标的句柄。
直接引用的目标一定是已经被加载进了虚拟机内存中的。

初始化

进行准备阶段时,变量已经赋过一次系统要求的初始零值,而在初始化阶段,则会根据程序员通 过程序编码制定的主观计划去初始化类变量和其他资源。

初始化阶段就是执行类构造器<clinit>()方法的过程。<clinit>()并不是程序员在Java代码中直接编写 的方法,它是Javac编译器的自动生成物。
<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,在执行子类的<clinit>()方法前,一定会先执行父类的<clinit>()方法。