对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解

简介: 对 JVM 的类加载机制以及寻找字节码文件的“双亲委派模型”的理解

1、JVM 的类加载机制

类加载指的是 Java 进程运行的时候,需要把 .class 文件从硬盘读取到内存,并进行一系列的校验解析的过程。

类加载的过程其实就是 .class 字节码文件转成 类对象 的过程,本质上也是数据从硬盘到内存的过程。


类加载大体的过程分为 5 个步骤(也有资料说 3 个,其实就是将 2,3,4 合并成 1 个):


1.1、加载

找到硬盘上的 .class 文件(使用双亲委派模型,下文将讲解),打开文件并读取文件内容(认为读到的是二进程数据)。


1.2、验证

验证当前读到的文件内容合法的 .class 字节码文件格式,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。具体的验证依据根据,在 Java 的虚拟机规范中有明确的格式说明。


虚拟机规范中的部分截图

1.3、准备

给类对象申请内存空间,此时申请到的内存空间都是默认值全0。


1.4、解析

解释阶段主要是针对类中的字符串常量进行处理,Java 虚拟机将常量池内的符号引用替换为直接引用的过程,也就是初始化常量的过程。


private String s = "hello";

上述代码中很显然,s 变量相当于保存了“hello”字符串常量的地址,但是在文件中,不存在“地址”的概念,地址是“内存”的地址,因此在硬盘的文件中使用类似地址的“偏移量”来表示。


而文件中给 s 填充的“hello”偏移量就可以认为是“符号引用”;


接下来将 .class 文件加载到内存后,会将字符串加载到内存中,此时“hello”就有地址了,就可以将当前“hello”真实的地址替换“偏移量”,称为“直接引用”;



1.5、初始化

针对类对象完成后续的初始化,还要执行静态代码块的逻辑,还可能触发父类的加载。


2、双亲委派模型

上述1.1、加载步骤中提到了要先从硬盘上找到 .class 文件,那么如何找呢?此时就需要使用到“双亲委派模型”,JVM 中有一个专门的模块“类加载器”(ClassLoader)来进行类加载的操作,即通过带有包名的类名(如 java.lang.String)来找到对应的 .class 文件。


JVM 中的 “类加载器” 默认有三个:


1、BootstrapClassLoader


负责查找标准库的目录。


2、ExtensionClassLoader


负责查找扩展库的目录。Java 语法规范里面描述了标准库中应该有哪些功能,但是实现 JVM 的厂商/组织也会在标准库的基础上扩充一些额外的功能库(不同厂商实现的 JVM 也可能有所不同)。


3、ApplicationClassLoader


负责查找当前项目的代码目录,以及第三方库的目录。


2.1、工作过程

1、从 applicationclassloader 作为入口,先开始工作。applicationclassloader不会立即搜索自己负责的目录,会把搜索的任务交给自己的父亲 extensionclassloader。


2、此时代码就进入到 extensionclassloader 范畴了,extensionclassloader也不会立即搜索自己负责的目录,也要把搜索的任务交给自己的父亲 bootstrapclassloader。


3、bootstrapclassloader 发现自己没有父亲,才会真正搜索负责的标准库目录,通过全限定类名,尝试在标志库中找到符合要求的 .class 文件,如果找到了,接下来就直接进入到打开文件/读文件等流程中,如果没找到则会返回到 extensionclassloader ,继续尝试加载,依此类推。


4、如果最后走到 applicationclassloader 依然没找到,此时说明类加载过程失败,就会抛出 classnotfoundexception 异常。




目录
相关文章
|
4天前
|
存储 Java 索引
深入浅出JVM(十)之字节码指令(下篇)
深入浅出JVM(十)之字节码指令(下篇)
|
4天前
|
存储 Java 索引
深入浅出JVM(九)之字节码指令(上篇)
深入浅出JVM(九)之字节码指令(上篇)
|
5天前
|
存储 前端开发 Java
深入浅出JVM(四)之类文件结构
深入浅出JVM(四)之类文件结构
深入浅出JVM(四)之类文件结构
|
4天前
|
存储 缓存 安全
深入浅出JVM(三)之HotSpot虚拟机类加载机制
深入浅出JVM(三)之HotSpot虚拟机类加载机制
|
4天前
|
Arthas 运维 监控
JVM工作原理与实战(四):字节码常用工具
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了字节码常用工具javap、jclasslib、Arthas等内容。
34 3
|
4天前
|
存储 缓存 算法
深入浅出JVM(二)之运行时数据区和内存溢出异常
深入浅出JVM(二)之运行时数据区和内存溢出异常
|
4天前
|
存储 Java
深入理解Java虚拟机:JVM内存模型
【4月更文挑战第30天】本文将详细解析Java虚拟机(JVM)的内存模型,包括堆、栈、方法区等部分,并探讨它们在Java程序运行过程中的作用。通过对JVM内存模型的深入理解,可以帮助我们更好地编写高效的Java代码,避免内存溢出等问题。
|
4天前
|
Java Linux Arthas
linux上如何排查JVM内存过高?
linux上如何排查JVM内存过高?
606 0
|
4天前
|
存储 缓存 算法
深入浅出JVM(十四)之内存溢出、泄漏与引用
深入浅出JVM(十四)之内存溢出、泄漏与引用
|
4天前
|
存储 缓存 Java
JVM 运行时内存篇
JVM 运行时内存篇
9 0