JVM虚拟机全面解析笔记
一、为什么要学JVM?
- 面试必备:避免死记硬背八股文
- 技术根基:理解代码底层逻辑,构建可靠系统
- 调优基础:解决线上内存泄漏、OOM崩溃等性能问题
核心观点:学JVM是自主解决问题的一流程序员与CRUD二流程序员的分水岭!
二、Class文件规范
1. Class文件结构
- 魔数标识:所有Class文件以
CAFE BABE
开头(Java名称起源) - 版本号机制:
minor_version(次版本) + major_version(主版本,如JDK8=52)
JDK8无法执行JDK17编译的Class文件(版本号61)
- 常量池索引:从1开始(索引0表示“不引用常量项”)
2. 字节码指令
- 指令格式:1字节操作码 + 0~N个操作数
- 核心指令类型:
bipush 10 // 压栈常量10(需操作数) astore_1 // 存储到局部变量表(无操作数) invokestatic // 调用静态方法
- 方法调用指令:
指令 用途 invokevirtual
对象实例方法(多态) invokeinterface
接口方法 invokespecial
构造方法/私有方法/父类方法 invokestatic
静态方法 invokedynamic
动态解析(Lambda底层)
3. 关键案例解析
Integer缓存机制:
Integer i1 = 10; // → bipush 10 + invokestatic Integer.valueOf
Integer i2 = 10;
System.out.println(i1 == i2); // true(-128~127缓存复用)
字节码验证:
valueOf
调用导致缓存对象复用
4. try-catch-finally流程
- 异常表控制跳转:
Start PC | End PC | Handler PC | CatchType
- try块异常 → catch或finally
- catch块异常 → finally
5. 字节码执行原理
- 操作数栈:存储计算中间结果(LIFO结构)
- 局部变量表:存储方法参数和局部变量(数组结构)
- i++ vs ++i:
int k = 1; k = k++; // 字节码:iload → iinc → istore(结果k=1)
三、类加载机制
1. JDK8类加载体系
- 双亲委派核心代码:
protected Class<?> loadClass(String name, boolean resolve) { // 1. 检查缓存 // 2. 父加载器优先加载 // 3. 父类失败时自身加载 }
打破场景:Tomcat多应用隔离加载
2. 沙箱保护机制
- 禁止覆盖核心类:
if (name.startsWith("java.")) { throw new SecurityException(); }
3. 类与对象关系
- 元空间(Metaspace):存储类元信息(JDK8取代PermGen)
- 对象头结构(JOL工具查看):
Mark Word(锁状态/GC年龄) + Class Pointer(指向元空间类)
四、执行引擎
1. 执行模式
模式 | 特点 | 启用参数 |
---|---|---|
解释执行 | 逐条翻译执行(启动快) | -Xint |
编译执行 | 编译为本地代码(执行快) | -Xcomp |
混合模式 | 默认策略(平衡性能) | (JDK8默认) |
2. JIT分层编译
- C1编译器:轻量优化(启动快)
- C2编译器:激进优化(峰值性能高)
- Graal编译器:JDK10+替代C2(Java编写)
五、GC垃圾回收
1. 分代收集模型
- 年轻代(Eden+Survivor):
- 比例:Eden:S0:S1 = 8:1:1
- 回收算法:标记-复制(Minor GC)
- 老年代:
- 回收算法:标记-整理(Full GC)
2. 垃圾回收器演进
分代类型 | 回收器 | 特点 |
---|---|---|
分代 | Serial/Parallel Scavenge | JDK8默认(Parallel+Old) |
CMS/G1 | 低停顿 | |
不分代 | ZGC/Shenandoah | TB级堆内存<10ms停顿 |
JDK8默认:
-XX:+UseParallelGC
(PS + PO)
六、GC调优实战
1. 关键JVM参数
-XX:+PrintGCDetails # 打印GC详情
-XX:+PrintGCTimeStamps # 增加时间戳
-Xloggc:./gc.log # 输出日志文件
2. 日志分析工具
- Arthas:实时监控JVM状态(阿里开源)
- GCeasy:在线分析GC日志(https://www.gceasy.io)
典型问题定位:
- YoungGC频繁 → 增大年轻代
- FullGC耗时久 → 检查老年代对象泄漏
总结思考
“JVM不是黑盒,是打开Java生态的钥匙” —— 掌握字节码、类加载、GC原理,方能从CRUD进阶系统级调优专家!