类加载各阶段的作用分别是什么?

  • 1. 加载

在加载阶段,虚拟机需要完成以下三件事情:

1、通过一个类的全限定名来获取定义此类的二进制字节流;

2、 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;

3、在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问接口。

  • 2. 验证

主要是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。验证阶段大致上分为 4 个阶段的检验动作:文件格式验证、元数据验证、字节码验证、符号引用验证。

1、文件格式校验:验证字节流是否符合 class 文件的规范,并且能被当前版本的虚拟机处理。只有通过这个阶段的验证后,字节流才会进入内存的方法区进行存储,所以后面的3个阶段的全部是基于方法区的存储结构进行的,不会再直接操作字节流;

2、 元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合 Java 语言规范的要求。目的是保证不存在不符合 Java 语言规范的元数据信息;

3、 字节码验证:该阶段主要工作是进行数据流和控制流分析,保证被校验类的方法在运行时不会做出危害虚拟机安全的行为;

4、 符号引用验证:最后一个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接的第三个阶段——解析阶段中发生。符号引用验证的目的是确保解析动作能正常执行。

  • 3. 准备

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配**。这时候进行内存分配的仅包括类变量(被 static 修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在 Java 堆中。实例化不是类加载的一个过程,类加载发生在所有实例化操作之前,并且类加载只进行一次,实例化可以进行多次。

初始值是默认值 0 或 false 或 null。如果类变量是常量(final),那么会按照表达式来进行初始化,而不是赋值为 0。public static final int value = 123;

  • 4. 解析

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

  • 5. 初始化

在准备阶段,变量已经赋过一次系统要求的初始值了,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器 () 方法的过程。

发表评论

后才能评论

评论(1)

  • foo('-'); 普通 2021-12-25 1:13 上午

    加载阶段,二进制元数据是存在方法区,Class对象是作为加载的产物分配在堆区中的!