Java类加载机制

2018-05-31  本文已影响4人  PaulLuv

Java类加载的生命周期

加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载
加载、验证、准备、初始化和卸载 这五个阶段的顺序是确定的。

Java类加载的时机

  1. 遇到 new、getStatic、setStatic、invokeStatic这四条字节码指令的时候。
    (使用new关键字初始化实例对象读取/设置一个类的静态字段(被final修饰、已经在编译器放入常量池的静态字段除外)、调用一个类的静态方法
  2. 使用 java.lang.reflect进行反射调用的时候。
  3. 当初始化一个类的时候,发现其父类还没有初始化,那么先去初始化它的父类
  4. 虚拟机启动的时候,需要初始化main函数所在的类

上面的四种场景的行为被称为对一个类的主动引用。除此之外的引用类的方式

Java类的加载

Java类的加载是Java类加载过程的第一个阶段,需要做的事情有:

Java类的连接

1. 验证

确保Class文件的字节流中包含的信息符合当前的虚拟机的要求,并且不会危害虚拟机自身的安全
主要包含以下四个阶段:

2. 准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段
注意
首先是这时候进行内存分配的仅包括类变量(被static修饰的变量),不包括实例变量。实例变量将会在对象实例化时随着对象一起分配在Java堆中。
其次这里所说的初始值通常情况下是数据类型的零值

这里示例讲解一下通常情况
假设一个类变量的定义为:

public static int value = 123;

那么变量value在准备阶段过后的初始值为0而不是123,因为这时候尚未开始执行任何Java方法,而把value赋值为123的putstatic指令是程序被编译后,存放与类构造器<clinit>()方法之中,所有把value赋值为123的动作将在初始化阶段才会被执行。

特殊情况
如果类字段的字段属性表中存在ConstantValue属性,那在准备阶段变量value就会被初始化为ConstantValue属性所指定的值。

public static final int value = 123;

编译时Javac将会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将value赋值为123。

3. 解析

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

Java类的初始化

类初始化阶段是类加载过程的最后一步,前面的类加载过程中,除了在加载阶段用户应用程序可以通过自定义类加载器参与外,其余动作完全由虚拟机主导和控制。初始化阶段才真正执行类中定义的Java程序代码(或者说是字节码)。

在准备阶段,变量已经赋过一次系统要求的初始值。
初始化阶段是执行类构造器<clinit>()方法的过程

主要阅读《深入理解Java虚拟机》一书

上一篇下一篇

猜你喜欢

热点阅读