1、JVM内存模型剖析及优化
一、JVM内存结构图解
关键组件说明:
-
堆(Heap)
- 存储所有对象实例和数组
- 分代结构:
- GC过程:
- Young GC:Eden→Survivor(分代年龄+1)
- Full GC:回收整个堆(STW明显)
-
虚拟机栈
- 栈帧组成:
- 局部变量表(基本类型/对象引用)
- 操作数栈
- 动态链接
- 方法出口
- StackOverflowError示例:
// -Xss128k时递归约700次崩溃 void redo() { count++; redo(); }
- 栈帧组成:
-
方法区(元空间)
- JDK8变化:
版本 实现 关键参数 ≤JDK7 PermGen -XX:PermSize ≥JDK8 Metaspace -XX:MetaspaceSize
- JDK8变化:
二、GC与STW深度解析
STW触发场景:
-
必然暂停:
- Young GC(所有实现)
- Full GC(含CMS重新标记阶段)
- 元空间扩容(触发Full GC)
-
优化手段对比:
GC类型 STW时间 适用场景 Serial 100ms+ 客户端小应用 G1 10-200ms 大堆应用(JDK8+默认) ZGC <1ms 超大堆(JDK15+)
引用更新机制:
三、JVM参数配置手册
1. 基础参数模板
java -Xms2048M -Xmx2048M \ # 堆大小(生产环境建议相同)-Xmn1024M \ # 新生代大小(建议占堆1/3-1/2)-Xss512K \ # 线程栈大小(默认1M)-XX:MetaspaceSize=256M \ # 元空间初始阈值-XX:MaxMetaspaceSize=256M \# 避免动态扩容Full GC-jar app.jar
2. 进阶调优参数
参数 | 作用说明 | 推荐值 |
---|---|---|
-XX:NewRatio | 新生代/老年代比例 | 2(默认) |
-XX:SurvivorRatio | Eden/Survivor比例 | 8(默认) |
-XX:MaxTenuringThreshold | 对象晋升老年代年龄阈值 | 15(默认) |
-XX:+UseG1GC | 启用G1收集器 | JDK8+推荐 |
3. 内存问题诊断工具
jstat -gcutil <pid> 1000 # 实时GC监控
jmap -heap <pid> # 堆内存分析
jstack <pid> > thread_dump.log # 线程栈分析
四、常见问题
Q1:对象引用更新过程?
A:Minor GC时通过GC Roots扫描记录引用关系,对象复制后:
- 维护跨代引用卡表(Card Table)
- 写屏障(Write Barrier)更新引用
- 最终批量修正指针
Q2:如何设置MetaspaceSize?
A:建议设置为相同值(如256M),避免运行时因阈值调整触发Full GC。监控建议:
jstat -gcmetacapacity <pid>
Q3:-Xss设置过小的影响?
A:单个线程栈帧容量↓ → 递归深度↓,但可创建线程数↑。需平衡:
- 计算密集型:增大栈空间(1-2M)
- 高并发服务:减小栈空间(256-512K)