Jvm类的加载机制

267 阅读2分钟

1、类的加载

我们在编写的JAVA代码,通过javac编译成class文件,称为字节码。jvm将其加载,解释成机器码执行。jvm加载class文件的过程称之为累加载,在jdk1.8讲类信息加载去元空间,当我们代码执行需要根据对应的类创建对象,这便是类的最终产物。

2、类的加载过程

截屏2021-06-25 23.52.07.png

  1. 加载阶段 当代码中使用(初次)某个类的信息,此时就会从对应的“.class”字节码文件加载对应的类到内存里来。

  2. 验证、准备、解析、初始化 验证:校验你加载进来的“.class”文件中的内容,是否符合JVM的规范

准备:给类空间分配内存空间,给类变量分配内存空间(static)修饰

解析:解析阶段将符号引用替换为直接引用。解析可以发生在初始化之前(静态解析),也可以发生在初始化之后(动态解析,比如多态,后期绑定)。

初始化:初始化阶段就是执行类的构造器方法(不是构造方法) clinit() 的过程。该方法无需定义,是 javac 编译器自动收集类中 所有类变量的赋值动作 和 静态代码块中 的语句合并而来的。 clinit() 中的指令是按照 代码的语句顺序 依次排列执行,虚拟机必须保证一个类的 clinit() 方法在多线程下同步加锁。 主要两步:为类变量赋值;执行静态代码块。

3、类的加载器和双亲委派机制

在了解类加载过程之后,我们进一步了解下加载器。

  1. 启动类加载器:Bootstrap ClassLoader:这个加载器不是一个Java类,而是由底层的c++实现,负责在虚拟机启动时加载Jdk核心类库(如:rt.jar、resources.jar、charsets.jar等)以及加载后两个类加载器。这个ClassLoader完全是JVM自己控制的,需要加载哪个类,怎么加载都是由JVM自己控制,别人也访问不到这个类。

  2. 扩展类加载器:Extension ClassLoader:是一个普通的Java类,继承自ClassLoader类,负责加载{JAVA_HOME}/jre/lib/ext/目录下的所有jar包。

  3. 应用程序加载器:是Extension ClassLoader的子对象,负责加载应用程序classpath目录下的所有jar和class文件。

  4. 自定义类加载器:自定义类加载器,去根据你自己的需求加载你的类

  5. 双亲外派机制:假设你的应用程序类加载器需要加载一个类,他首先会委派给自己的父类加载器去加载,最终传导到顶层的类加载器去加载 但是如果父类加载器在自己负责加载的范围内,没找到这个类,那么就会下推加载权利给自己的子类加载器。