对 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 异常。




目录
相关文章
|
8月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
767 55
|
6月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
167 0
|
9月前
|
Arthas 监控 Java
Arthas redefine(加载外部的.class文件,redefine到JVM里 )
Arthas redefine(加载外部的.class文件,redefine到JVM里 )
419 15
|
8月前
|
Arthas 存储 Java
JVM深入原理(三+四):JVM组成和JVM字节码文件
目录3. JVM组成3.1. 组成-运行时数据区3.2. 组成-类加载器3.3. 组成-执行引擎3.4. 组成-本地接口4. JVM字节码文件4.1. 字节码文件-组成4.1.1. 组成-基础信息4.1.1.1. 基础信息-魔数4.1.1.2. 基础信息-主副版本号4.1.2. 组成-常量池4.1.3. 组成-方法4.1.3.1. 方法-工作流程4.1.4. 组成-字段4.1.5. 组成-属性4.2. 字节码文件-查看工具4.2.1. javap4.2.2. jclasslib4.2.3. 阿里Arthas
151 0
|
8月前
|
存储 安全 Java
JVM深入原理(五):JVM组成和JVM字节码文件
类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析。
123 0
|
存储 Java 程序员
【JVM】——JVM运行机制、类加载机制、内存划分
JVM运行机制,堆栈,程序计数器,元数据区,JVM加载机制,双亲委派模型
354 10
|
SQL 缓存 Java
JVM知识体系学习三:class文件初始化过程、硬件层数据一致性(硬件层)、缓存行、指令乱序执行问题、如何保证不乱序(volatile等)
这篇文章详细介绍了JVM中类文件的初始化过程、硬件层面的数据一致性问题、缓存行和伪共享、指令乱序执行问题,以及如何通过`volatile`关键字和`synchronized`关键字来保证数据的有序性和可见性。
200 3
|
3月前
|
存储 缓存 Java
我们来说一说 JVM 的内存模型
我是小假 期待与你的下一次相遇 ~
312 5
|
3月前
|
存储 缓存 算法
深入理解JVM《JVM内存区域详解 - 世界的基石》
Java代码从编译到执行需经javac编译为.class字节码,再由JVM加载运行。JVM内存分为线程私有(程序计数器、虚拟机栈、本地方法栈)和线程共享(堆、方法区)区域,其中堆是GC主战场,方法区在JDK 8+演变为使用本地内存的元空间,直接内存则用于提升NIO性能,但可能引发OOM。
|
9月前
|
Arthas 监控 Java
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
755 6