学习笔记03——《深入理解Java虚拟机(第三版)》类加载机制知识总结与面试核心要点
《深入理解Java虚拟机(第三版)》类加载机制知识总结与面试核心要点
一、章节核心脉络
核心命题:JVM如何将.class文件加载到内存并转换为运行时数据结构?
核心流程:加载 → 验证 → 准备 → 解析 → 初始化 → 使用 → 卸载
三大核心机制:
- 类加载过程(双亲委派模型)
- 类初始化触发条件(主动引用 vs 被动引用)
- 类加载器体系(Bootstrap、Extension、Application、自定义加载器)
二、类加载机制深度解析
1. 类加载生命周期
阶段 | 关键行为 | 示例/注意事项 |
---|---|---|
加载 | 1. 获取.class二进制流 2. 转换为方法区数据结构 3. 生成 Class 对象 | 可从ZIP包、网络、动态代理等来源加载 |
验证 | 文件格式验证、元数据验证、字节码验证、符号引用验证 | 防止恶意代码注入(如魔数CAFE BABE 验证) |
准备 | 为类变量(static变量)分配内存并赋初始值(零值) | static int x=5; 在此阶段x=0 |
解析 | 将符号引用转换为直接引用(方法、字段、接口方法) | 可能触发其他类的加载(如父类或接口) |
初始化 | 执行<clinit>() 方法(静态变量赋值 + static块) | 多线程环境下JVM保证同步执行 |
类初始化触发条件(主动引用):
new
、getstatic
、putstatic
、invokestatic
指令- 反射调用(
Class.forName()
) - 子类初始化触发父类初始化
- 主类(包含main方法的类)
被动引用示例(不会触发初始化):
- 通过子类访问父类静态字段
- 通过数组定义引用类(
MyClass[] arr = new MyClass[10];
) - 访问类的
final static
常量(编译期优化)
2. 类加载器体系与双亲委派模型
(1) 类加载器分类
类加载器 | 加载路径 | 实现语言 | 是否可自定义 |
---|---|---|---|
Bootstrap ClassLoader | jre/lib 目录(rt.jar等核心库) | C++ | ❌ |
Extension ClassLoader | jre/lib/ext 目录 | Java | ❌ |
Application ClassLoader | CLASSPATH 环境变量或用户类路径 | Java | ❌ |
Custom ClassLoader | 自定义路径(网络、加密文件等) | Java | ✅ |
(2) 双亲委派模型工作流程
核心规则:
- 收到类加载请求后,优先委派父加载器处理
- 所有父加载器无法完成时,才由自己加载
设计优势:
- 避免重复加载(如核心类
java.lang.Object
) - 安全防护(防止用户自定义类冒充核心类)
破坏双亲委派的场景:
- SPI机制(JDBC驱动加载,使用线程上下文类加载器
ThreadContextClassLoader
) - OSGi模块化热部署
- Tomcat容器隔离(不同Web应用使用独立类加载器)
3. 自定义类加载器实现
关键步骤:
- 继承
ClassLoader
类 - 重写
findClass()
方法(非loadClass()
,避免破坏双亲委派) - 通过
defineClass()
将字节码转换为Class对象
代码示例:
public class MyClassLoader extends ClassLoader { @Override protected Class<?> findClass(String name) { byte[] classData = loadClassData(name); return defineClass(name, classData, 0, classData.length); } // 从自定义路径加载字节码...
}
三、高频面试问题与答案要点
1. 类加载过程与双亲委派模型
问题:描述类加载过程,双亲委派模型的作用及如何打破?
答:
- 过程:加载→验证→准备→解析→初始化(重点说明各阶段核心任务)
- 双亲委派作用:避免重复加载、保证核心类安全
- 打破方式:重写
loadClass()
方法、使用线程上下文类加载器(如JDBC SPI)
2. ClassNotFoundException vs NoClassDefFoundError
问题:二者的区别是什么?
答:
- ClassNotFoundException:类加载器在类路径中找不到目标类(如
Class.forName()
失败) - NoClassDefFoundError:JVM在运行时找不到类的定义(编译时存在,运行时缺失或初始化失败)
3. 类初始化顺序问题
问题:父类和子类的静态代码块、构造代码块执行顺序?
答:
- 父类静态块 → 子类静态块
- 父类构造代码块 → 父类构造函数
- 子类构造代码块 → 子类构造函数
4. Tomcat类加载机制
问题:Tomcat如何实现不同Web应用隔离?
答:
- 每个Web应用使用独立的
WebappClassLoader
- 优先加载
/WEB-INF/classes
和/WEB-INF/lib
下的类 - 通过破坏双亲委派实现应用间类隔离
5. SPI机制原理
问题:JDBC如何通过SPI加载驱动?
答:
- 核心接口由Bootstrap加载器加载(如
java.sql.Driver
) - 具体实现类由线程上下文类加载器加载(如
com.mysql.cj.jdbc.Driver
)
四、实战问题排查与工具
1. 类冲突排查
现象:java.lang.LinkageError
或方法调用不一致
工具:
-verbose:class
参数打印类加载日志jcmd <pid> VM.classloader_stats
查看类加载器统计
2. 热替换实现原理
方案:自定义类加载器每次加载新版本类,旧版本类无法卸载(PermGen/Metaspace限制)
五、扩展思考
- 模块化系统影响:JDK9+的模块化(Jigsaw)如何改变类加载机制?
- 模块化路径取代类路径
- 新增
Layer
概念实现模块隔离
- 动态加载应用:如何实现类似Spring的Bean动态加载?
学习建议:结合javap -c
反编译工具观察<clinit>
和<init>
方法,通过Arthas等工具动态跟踪类加载过程。
相关文章:
学习笔记03——《深入理解Java虚拟机(第三版)》类加载机制知识总结与面试核心要点
《深入理解Java虚拟机(第三版)》类加载机制知识总结与面试核心要点 一、章节核心脉络 核心命题:JVM如何将.class文件加载到内存并转换为运行时数据结构? 核心流程:加载 → 验证 → 准备 → 解析 → 初始化 → 使用 →…...

w227springboot旅游管理系统设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
漏洞文字版表述一句话版本(漏洞危害以及修复建议),通常用于漏洞通报中简洁干练【持续更新中】
漏洞文字版表述一句话版本(漏洞危害以及修复建议) SQL注入漏洞 危害描述: SQL注入漏洞允许攻击者通过构造恶意的SQL语句,绕过应用程序的安全检查,直接访问或操作数据库。这可能导致数据泄露、数据篡改、甚至数据库被删除等严重后果…...

项目——仿RabbitMQ实现消息队列
1.项目介绍 曾经在学习Linux的过程中,我们学习过阻塞队列 (BlockingQueue) 。 当时我们说阻塞队列最大的用途, 就是用来实现生产者消费者模型。 生产者消费者模型是后端开发的常用编程方式, 它存在诸多好处: 解耦合支持并发支持忙闲不均削峰…...
嵌入式硬件篇---滤波器
文章目录 前言一、模拟电子技术中的滤波器1. 基本概念功能实现方式 2. 分类按频率响应低通滤波器高通滤波器带通滤波器带阻滤波器 按实现方式无源滤波器有源滤波器 3. 设计方法巴特沃斯滤波器(Butterworth)切比雪夫滤波器(Chebyshevÿ…...

JAVA最新版本详细安装教程(附安装包)
目录 文章自述 一、JAVA下载 二、JAVA安装 1.首先在D盘创建【java/jdk-23】文件夹 2.把下载的压缩包移动到【jdk-23】文件夹内,右键点击【解压到当前文件夹】 3.如图解压会有【jdk-23.0.1】文件 4.右键桌面此电脑,点击【属性】 5.下滑滚动条&…...
《筑牢元宇宙根基:AI与区块链的安全信任密码》
在科技浪潮汹涌澎湃的当下,元宇宙已不再是科幻作品中的遥远构想,而是逐渐步入现实,成为人们热议与探索的前沿领域。从沉浸式的虚拟社交,到创新的数字经济模式,元宇宙的发展前景广阔,潜力无限。但要让元宇宙…...
云原生周刊:云原生和 AI
开源项目推荐 FlashMLA DeepSeek 于北京时间 2025 年 2 月 24 日上午 9 点正式开源了 FlashMLA 项目。FlashMLA 是专为 NVIDIA Hopper 架构 GPU(如 H100、H800)优化的高效多头潜在注意力(MLA)解码内核,旨在提升大模型…...
rust笔记9-引用与原始指针
Rust 中的指针类型和引用类型是理解其内存管理机制的关键部分。& 引用和 * 原始指针在底层原理上确实都可以认为是指针,它们都存储了某个内存地址,并指向该地址处的数据。然而,它们在安全性、使用方式和编译器支持上有显著的区别。下面我会详细解释它们的异同点,帮助你…...

信而泰CCL仿真:解锁AI算力极限,智算中心网络性能跃升之道
引言 随着AI大模型训练和推理需求的爆发式增长,智算中心网络的高效性与稳定性成为决定AI产业发展的核心要素。信而泰凭借自主研发的CCL(集合通信库)评估工具与DarYu-X系列测试仪,为智算中心RoCE网络提供精准评估方案,…...

本地部署AI模型 --- DeepSeek(二)---更新中
目录 FAQ 1.Failed to load the model Exit code: 18446744072635812000 FAQ 1.Failed to load the model Exit code: 18446744072635812000 问题描述: 🥲 Failed to load the model Error loading model. (Exit code: 18446744072635812000). Unkn…...
c++类知识点复习与总结
类 c 是一种人机交互的面向对象的编程语言,面向对象思想主要体现在 类 上。 类是具有相同属性和相同行为的对象的集合, 具有封装,继承,多态的特性。 类的定义 class 类名 { }; 封装 例如:人就是一种类…...

C++的allactor
https://zhuanlan.zhihu.com/p/693267319 1 双层内存配置器 SGI设计了两层的配置器,也就是第一级配置器和第二级配置器。同时为了自由选择,STL又规定了 __USE_MALLOC 宏,如果它存在则直接调用第一级配置器,不然则直接调用第二级配…...

【2025深度学习环境搭建-2】pytorch+Docker+VS Code+DevContainer搭建本地深度学习环境
上一篇文章:【2025深度学习环境搭建-1】在Win11上用WSL2和Docker解锁GPU加速 先启动Docker!对文件内容有疑问,就去问AI 一、用Docker拉取pytorch镜像,启动容器,测试GPU docker pull pytorch/pytorch:2.5.0-cuda12.4…...

在CentOS 7上安装和使用Spleeter音频分离工具的详细步骤
在音频处理领域,Spleeter是一款优秀的开源工具,能够帮助用户轻松实现音频文件中人声和背景音的分离。本文将详细介绍在CentOS 7系统上安装和配置Spleeter的步骤,以及如何使用Spleeter进行音频分离。 准备环境: 在开始安装Spleeter之前&…...

【1】VS Code 新建上位机项目---C#基础语法
VS Code 新建上位机项目---C#基础语法 1 基本概念1.1 准备工具1.2 新建项目2 C#编程基础2.1 命名空间和类2.2 数据类型2.3 控制台输入输出2.3.1 输入输出: write 与 read2.3.2 格式化 : string.Foramt() 与 $2.3.3 赋值与运算2.4 类型转换2.4.1 数值类型之间的转换:(int)2.4…...
电脑经常绿屏(蓝屏)怎么办(解决方法)?
一、排查系统与驱动问题 进入安全模式修复系统 强制重启电脑 3 次触发恢复环境,选择 疑难解答 > 高级选项 > 启动设置 > 重启,按 F5 或 5 进入带网络连接的安全模式3。 在安全模式下,尝试卸载最近安装的软件或更新,尤其…...

clickhouse--本地表和分布式表,副本机制,分片集群
1、本地表和分布式表 ck的表分为两种: 分布式表 一个逻辑上的表,可以理解为数据库中的视图,一般查询都查询分布式表。分布式表引擎会将我们的查询请求路由本地表进行查询,然后进行汇总最终返回给用户。本地表 实际存储数据的表。 …...
react hook useReducer
useReducer useReducer 是 React 中用于状态管理的 Hook,与 useState 不同,它更适合处理复杂的状态逻辑. const [state, dispatch] useReducer(reducer, initialArg, init?) reducer 是一个处理函数,用于更新状态, reducer 里面包含了两个…...
告别阻塞,迎接高效:掌握 AsyncIOScheduler 实现异步任务调度
前言 时间在编程中是宝贵的,直接关联到效率与灵活性,尤其在异步编程里,如何优雅地管理定时任务简直是一门“艺术”。如果你还在用 time.sleep() 来控制延时任务,恐怕你早已体会过它的“痛苦”:程序卡住、线程阻塞、性能急剧下滑。想象一下,你的程序如同一个永远无法按时…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...