学习笔记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() 来控制延时任务,恐怕你早已体会过它的“痛苦”:程序卡住、线程阻塞、性能急剧下滑。想象一下,你的程序如同一个永远无法按时…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
