JVM的类加载器

什么是类加载器?

**类加载器:**JVM只会运行二进制文件,类加载器的作用就是将字节码文件加载到JVM中,从而Java

程序能够启动起来。

类加载器有哪些?

**启动类加载器(BootStrap ClassLoader):**加载JAVA HOME/jre/lib目录下的库

**扩展类加载器(ExtClassLoader):**主要加载JAVA HOME/jre/lib/ext目录中的类

**应用类加载器(AppClassLoader):**用于加载classPath下的类。是默认的类加载器,一般来说,java

应用的类都是由该加载器加载的。

在java的日常应用开发中,类的加载基本上都是由这三种加载器互相配合完成加载的。

**自定义类加载器(CustomizeClassLoader):**自定义类继承ClassLoader,实现自定义类加载规则。

什么是双亲委派模型?

加载某一个类,先委托上一级的加载器进行加载,如果上级加载器也有上级,则会继续向上委托

如果该类委托上级没有被加载,子加载器尝试加载该类

举例

在加载Student类时,应用类加载器会委派扩展类加载器,扩展类加载器会委派启动类加载器,启动类加载器不会加载,扩展类不会加载,然后应用类加载器加载Student类

JVM为什么会采用双亲委派机制?

(1)通过双亲委派机制可以避免某一个类被重复加载,当父类已经加载后则无需重复加载,保证唯

一性。

(2)为了安全,保证类库API不会被修改

例子

类装载的执行过程

类从加载到虚拟机中开始,直到卸载为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载 这7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)

加载阶段:

  • 通过类的全名,获取类的二进制数据流。
  • 解析类的二进制数据流为方法区内的数据结构(Java类模型)
  • 创建java.lang.Class类的实例,表示该类型。作为方法区这个类的各种数据的访问入口

验证阶段:验证类是否符合JVM的规范,安全性检查

准备阶段:为类变量分配内存并设置类变量的初始值

  • static变量,分配空间在准备阶段完成(设置默认值),赋值在初始化阶段完成
  • static变量是final的基本类型,以及字符串常量,值已确定,赋值在准备阶段完成
  • static变量是final的引用类型,那么赋值也会在初始化阶段完成
例子

变量b分配空间在准备阶段完成(设置默认值0),赋值在初始化阶段完成 b=10

变量c 和 变量d 值已确定,赋值在准备阶段完成

变量obj 赋值也会在初始化阶段完成

解析阶段:把类中的符号引用转换为直接引用

符号引用和直接引用的例子

比如:方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接指向方法

初始化阶段:对类的静态变量,静态代码块执行初始化操作

  • 如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类
  • 如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
案例:
复制代码
public class Application {
    public static void main(String[] args) {
        // 1. 首次访问这个类的静态变量或静态方法时
        System.out.println(Animal.num);
        // 2. 子类初始化,如果父类还没初始化,会引发父类先初始化
        System.out.println(Cat.sex);
        // 3. 子类访问父类静态变量,只触发父类初始化
        System.out.println(Cat.num);
    }
}

class Animal {
    static int num = 55;
    static {
        System.out.println("Animal 静态代码块...");
    }
}

class Cat extends Animal {
    static boolean sex = false;
    static {
        System.out.println("Cat 静态代码块...1");
    }
    static {
        System.out.println("Cat 静态代码块...2");
    }
}

1.访问父类的变量

执行结果

2.访问子类的变量

3.子类访问父类的静态变量

使用阶段:

  • JVM 开始从入口方法开始执行用户的程序代码
  • 调用静态类成员信息(比如:静态字段、静态方法)
  • 使用new关键字为其创建对象实例

卸载阶段:当用户程序执行完毕之后,JVM便开始销毁创建的Class对象

总结:

加载:查找和导入class文件

验证:保证加载类的准确性

准备:为类变量分配内存并设置类变量初始值

解析:把类中的符号引用转换为直接引用

初始化:对类的静态变量,静态代码块执行初始化操作

使用:JVM 开始从入口方法开始执行用户的程序代码

卸载:当用户程序代码执行完毕后,JM便开始销毁创建的Class对象。

相关推荐
唐古乌梁海17 分钟前
【Java】JVM 内存区域划分
java·开发语言·jvm
众俗1 小时前
JVM整理
jvm
echoyu.1 小时前
java源代码、字节码、jvm、jit、aot的关系
java·开发语言·jvm·八股
代码栈上的思考16 小时前
JVM中内存管理的策略
java·jvm
thginWalker19 小时前
深入浅出 Java 虚拟机之进阶部分
jvm
沐浴露z19 小时前
【JVM】详解 线程与协程
java·jvm
thginWalker21 小时前
深入浅出 Java 虚拟机之实战部分
jvm
程序员卷卷狗2 天前
JVM 调优实战:从线上问题复盘到精细化内存治理
java·开发语言·jvm
Sincerelyplz3 天前
【JDK新特性】分代ZGC到底做了哪些优化?
java·jvm·后端
初学小白...4 天前
线程同步机制及三大不安全案例
java·开发语言·jvm