JVM 的类加载机制

文章目录

    • JVM 的类加载机制
      • 类加载的 5 个过程
      • 什么时候进行类加载?
      • 双亲委派模型

JVM 的类加载机制

类加载就是把 .class 文件加载到内存中,得到 类对象 的过程。


类加载的 5 个过程

1 加载

找到 .class 文件,将文件内容读取到内存中。

2 验证

验证加载的这个文件是否合法的 .class文件,.class 文件有明确的数据格式。

3 准备

给类对象分配内存空间,定义成员变量。

未初始化的空间,内存空间中的数据是全 0 的。

例如: public static int value = 100;

此时这个成员变量的值为 0,而不是 100。

4 解析

针对字符串常量进行初始化。

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

常量池内的符号引用替换为直接引用:

字符串常量在 .class 文件中就存在了,但是它们只是知道彼此之间的相对位置(偏移量),这个时候的字符串常量就算符号引用。

加载到内存中后,字符串常量就填充到内存中,字符串常量之间的相对位置还是一样,但是这些字符串常量有了自己的内存地址,此时的字符串就算直接引用(Java 中的普通引用)。

5 初始化

针对类对象进行初始化(初始化静态成员,执行静态代码块,加载父类…)


什么时候进行类加载?

懒加载” 的策略,非必要,不加载。

  1. 创建类的实例,会加载这个类

  2. 使用了某个类的静态属性/静态方法

  3. 加载一个子类,会触发父类的加载


双亲委派模型

双亲委派模型所做的事,就是在 加载 步骤中,寻找 .class 文件。

在 JVM 中,加载类,需要用到一组特殊的模块,类加载器。

JVM 中,内置了三个类加载器:

  1. BootStrap ClassLoader 负责加载 Java 标准库中的类

  2. Extension ClassLoader 负责加载一些非标准的 Sum/ Oracle 扩展库中的类

  3. Application ClassLoader 负责加载项目中自己写的类 以及 第三方库中的类

这三个加载器有父子关系,Application ClassLoader 的父亲加载器是 Extension ClassLoader,Extension ClassLoader 的父亲加载器的 BootStrap ClassLoader。

寻找 .class 文件的过程:

加载一个类的时候,要先通过全限定类名,如 “java.lang.String",来寻找这个 .class 文件。

先从 Application ClassLoader 加载器开始,但是不能直接开始搜索,会先交给父亲加载器 Extension ClassLoader 去找。等收到父亲加载器的反馈后,自己才开始搜索,如果搜索到了直接进行后续的加载步骤,如果没有搜索到,就抛出 ClassNotFuoundException

Extension ClassLoader 也不能直接开始搜索,也会先交给自己的父亲加载器 BootStrap ClassLoader 去找。等收到父亲加载器的反馈后,自己才开始搜索,如果搜索到了,就直接进行后续的加载步骤,如果没有搜索到就交给孩子加载器。

BootStrap ClassLoader 没有父亲加载器了,就自己来搜索,搜索到了就直接进行后续的加载步骤,如果没有搜索到再交给孩子加载器。

总结: 搜索一个 .class 文件,先从 Application ClassLoader 加载器开始,然后每个加载器都会先交给自己的父亲加载器去搜索,父亲加载器搜索不到,自己才会开始搜索,如果 Application ClassLoader 也搜索不到,就会抛出 ClassNotFuoundException。


你可能感兴趣的:(jvm)