JVM 的类加载机制
类加载就是把 .class 文件加载到内存中,得到 类对象 的过程。
类加载的 5 个过程
1 加载
找到 .class 文件,将文件内容读取到内存中。
2 验证
验证加载的这个文件是否合法的 .class文件,.class 文件有明确的数据格式。
3 准备
给类对象分配内存空间,定义成员变量。
未初始化的空间,内存空间中的数据是全 0 的。
例如: public static int value = 100;
此时这个成员变量的值为 0,而不是 100。
4 解析
针对字符串常量进行初始化。
解析阶段是 Java 虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。
常量池内的符号引用替换为直接引用:
字符串常量在 .class 文件中就存在了,但是它们只是知道彼此之间的相对位置(偏移量),这个时候的字符串常量就算符号引用。
加载到内存中后,字符串常量就填充到内存中,字符串常量之间的相对位置还是一样,但是这些字符串常量有了自己的内存地址,此时的字符串就算直接引用(Java 中的普通引用)。
5 初始化
针对类对象进行初始化(初始化静态成员,执行静态代码块,加载父类…)
什么时候进行类加载?
“懒加载” 的策略,非必要,不加载。
-
创建类的实例,会加载这个类
-
使用了某个类的静态属性/静态方法
-
加载一个子类,会触发父类的加载
双亲委派模型
双亲委派模型所做的事,就是在 加载 步骤中,寻找 .class 文件。
在 JVM 中,加载类,需要用到一组特殊的模块,类加载器。
JVM 中,内置了三个类加载器:
-
BootStrap ClassLoader 负责加载 Java 标准库中的类
-
Extension ClassLoader 负责加载一些非标准的 Sum/ Oracle 扩展库中的类
-
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
没有父亲加载器了,就自己来搜索,搜索到了就直接进行后续的加载步骤,如果没有搜索到再交给孩子加载器。文章来源:https://www.toymoban.com/news/detail-555275.html
总结: 搜索一个 .class 文件,先从 Application ClassLoader 加载器开始,然后每个加载器都会先交给自己的父亲加载器去搜索,父亲加载器搜索不到,自己才会开始搜索,如果 Application ClassLoader 也搜索不到,就会抛出 ClassNotFuoundException。文章来源地址https://www.toymoban.com/news/detail-555275.html
到了这里,关于JVM 的类加载机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!