怎样建立自己网站,沈阳市营商环境建设监督局网站,wordpress静态生成器,城乡建设部网站混凝土7天强度目录
前言
1.什么是类加载?
2.类加载整体流程
3.一个类什么时候被加载?
4.双亲委派模型
4.1 JVM默认提供了三个类加载器
4.1.1 BootstrapClassLoader
4.1.2 ExtensionClassLoader
4.1.3 ApplicationClassLoader
4.2 破坏双亲委派模型 前言
在上一篇文章中#xf…
目录
前言
1.什么是类加载?
2.类加载整体流程
3.一个类什么时候被加载?
4.双亲委派模型
4.1 JVM默认提供了三个类加载器
4.1.1 BootstrapClassLoader
4.1.2 ExtensionClassLoader
4.1.3 ApplicationClassLoader
4.2 破坏双亲委派模型 前言
在上一篇文章中我们主要简述了JVM内存区域划分的相关知识下面我们将讲述JVM类加载机制 1.什么是类加载? 类加载就是.class文件(.java通过javac进行编译成class文件)从文件(硬盘)被加载到内存中(元数据区)的过程。 2.类加载整体流程 1.加载把.class文件找到打开文件读文件把文件内容读到内存中
2.验证检查下.class文件格式是否规范
3.准备给类对象分配内存空间(先在元数据占个位置)也使静态成员被设置成0
4.解析初始化字符串常量把符号引用转为直接引用。初始化字符串常量时首先需要为字符的实际内容分配一块内存空间并确保有一个引用指向这块内存空间的起始地址。在类加载之前字符串常量存在于.class文件中这个引用记录的是它在文件中的偏移量占位符而不是字符串常量的真正地址。当类加载完成后字符串常量才会被放入内存中此时引用会被赋值为实际的内存地址。 举例假设你得到了一张古老的藏宝图这张藏宝图标记了一处隐藏的宝藏位置。这个过程与字符串常量的处理有类似之处 1. 藏宝图的研究类加载前在开始挖掘宝藏之前藏宝图就像是一个.class文件里的字符串常量。你知道这张图代表了什么但还没有实际的行动。图中标记的位置不是真实的地址而是告诉你宝藏可能在哪里的一种“偏移量”或线索 2. 准备挖掘类加载决定根据藏宝图去探险就好比是类加载的过程。你开始准备必要的工具如铲子和地图这相当于JVM为字符串常量分配内存空间 3. 定位宝藏引用转换出发后你按照藏宝图上的线索前进这如同符号引用被转换为直接引用。你通过解读地图上的线索可能是一棵树、一块石头或一个特定形状的地标逐步接近宝藏的实际位置。 4. 挖掘宝藏访问地址当你到达指定地点并开始挖掘时这就像是JVM访问字符串常量在内存中的实际位置。你挖出宝藏的那一刻就类似于程序最终使用到这个字符串常量的内容。 通过这个例子我们可以看到藏宝图的使用过程从解读到实际挖掘出宝藏与JVM如何处理字符串常量从类加载到实际使用字符串内容有着相似的步骤。都是先有一个初步的指引无论是藏宝图还是符号引用然后通过一系列的动作解读和应用最终达到目的找到宝藏或获取字符串内容。 5.初始化调用构造方法进行成员初始化执行代码块静态代码块加载父类等。
3.一个类什么时候被加载?
首先我们要知道不是Java程序一运行就把所有的类都加载而是真正用到才加载(懒汉模式)一旦加载过后后续无需再重复加载
加载的内容有: 1.构造类的实例2.调用这个类的静态方法/使用静态属性3.加载子类就会先加载其父类
4.双亲委派模型
在上面的类加载的整体流程中我们说到了加载 加载:把.class文件找到打开文件读文件把文件内容读到内存中 双亲委派模型描述了类加载器在查找和加载.class文件时的基本过程。 4.1 JVM默认提供了三个类加载器 4.1.1 BootstrapClassLoader 负责加载标准库的类 (Java规范要求提供哪些类)无论是哪种JVM的实现都会提供这些一样的类 4.1.2 ExtensionClassLoader 负责加载JVM扩展库中的类 (规范之外由实现JVM的厂商/组织提供的额外的功能) 4.1.3 ApplicationClassLoader 负责加载用户提供的第三方库/用户项目代码中的类上述的三个类存在父子关系相当于每个class loader有一个parent属性指向自己的父 类加载器 4.1.4 上述的类加载器如何配合工作? 1.首先类加载过程是从ApplicationClassLoader开始的。然而ApplicationClassLoader不会直接进行加载而是将加载任务委托给自己的父 类加载器。接下来ExtensionClassLoader接收到委托后同样不会立即加载而是再次将自己作为父类加载器并将加载任务委托给它的父 类加载器BootstrapClassLoader。BootstrapClassLoader在收到委托时发现自己没有父类加载器即父类为null于是它自己执行实际的加载操作。2.BootstrapClassLoader会搜索自己负责的标准库目录寻找相关的类。如果找到了目标类则进行加载如果没有找到它会将加载任务委托给子类加载器。ExtensionClassLoader会真正地搜索扩展库相关的目录同样地如果找到了目标类则进行加载如果没有找到它也会将加载任务委托给子类加载器。ApplicationClassLoader则会搜索用户相关的目录如果找到了目标类则进行加载如果没有找到由于此时已经没有其他子类加载器了所以只能抛出一个类找不到的异常。3.为什么要有上述顺序? 上述这套顺序实际上是由JVM实现代码的逻辑所决定的这种逻辑类似于递归的方式主要目的是确保Bootstrap能够优先加载而Application能够稍后加载以避免用户创建一些奇怪的类从而引发不必要的bug在一方面类加载器可以由用户自定义。除了JVM自带的Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader之外用户可以创建自己的类加载器并将其加入到类加载流程中。这样用户可以根据自己的需求决定加载顺序并且可以与现有的加载器配合使用。
4.2 破坏双亲委派模型 1.自己编写的类加载器可以根据需求选择是否遵守双亲委派模型。 2.举例来说Tomcat是一个Web服务器它需要加载Web应用程序中的类。在这种情况下Tomcat可能会使用单独的类加载器来加载Webapp而不是遵循双亲委派模型。 3.这样做的好处是可以避免不同Web应用程序之间的类冲突并且可以更好地控制每个Web应用程序的类加载过程。然而如果一个自定义的类加载器不遵循双亲委派模型那么它必须自行处理类的查找和加载这可能会导致一些额外的复杂性和潜在的问题。因此是否遵守双亲委派模型主要取决于具体的需求和设计决策。 以上就是JVM类加载机制的简单介绍。