标签:变量 eve 一个 类加载器 net 参考 链接 基础 family
0、前言
以下都是基于 HotSpot 虚拟机
1、JVM 的整体结构
概览图:
详细图:
运行时数据区详细解释:
JDK8 之后把方法区划成了元数据区域,其实元数据+JIT编译产物都可以称作非堆区
2、类的加载过程
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们的顺序如下图所示:
具体每一步都干了什么 => 参考链接
其中注意
1)链接(link)中的 准备(prepare)阶段会给类变量(用static修饰的)赋默认值,比如 int 的默认值是 0
2)加载(load)只负责将类的二进制信息加载进来,不负责其他。
3)类的初始化时机有触发条件,如下主动使用的情况
结合 2)和 3)于是就有了Class.forName 和 ClassLoader.load 的区别,参考此链接
3、类加载过程的类加载器
1) Bootstrap Class Loader
2) Extension Class Loader
3) Application Class Loader
BTW:
JVM中如何判断两个Class对象是否是同一个类需要满足两个条件
1)类的完整类名必须完全一致,包括包名
2)加载类的类加载器必须也是相同的!
也就是说,即便是同一个 Class 文件出来的类信息,只要使用的加载器不一样,那在 JVM 中就不能视为同一个类
4、关于 ClassLoader 类
注:点开 sun.misc.Launcher 源码可以看到 ExtClassLoader 和 AppClassLoader 是其内部类,而 Launcher 是由 BootstrapClassLoader 加载。详情可以参考此链接
在代码中可以有三种方式来获取 ClassLoader 类。详情参考此链接
5、双亲委派机制
好处 :这个机制保护了基础类不被蓄意 "破坏",例如类java.lang.Object,它存在在rt.jar,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的Bootstrap ClassLoader进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有双亲委派模型而是由各个类加载器自行加载的话,如果用户编写了一个java.lang.Object的同名类并放在ClassPath中,那系统中将会出现多个不同的Object类,程序将混乱。因此,如果开发者尝试编写一个与rt.jar类库中重名的Java类可以正常编译,但是永远无法被加载运行。
特殊情况:有时候父加载器需要子加载器对某些类进行加载,需要破坏原本的 "向上" 传递的规则 ,于是就有了 Thread.currentThread().getContextClassLoader() 具体参考此链接
标签:变量 eve 一个 类加载器 net 参考 链接 基础 family
原文地址:https://www.cnblogs.com/qwertiLH/p/12505440.html