学习笔记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&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
