第3章 JVM调优与内存模型面试高频

JVM调优是Java分布式系统面试的必考点,涵盖内存分区、GC算法、参数配置与内存泄漏排查。本章以结构化问答+实战项目模板,帮助你在面试中体系化输出调优思路。

明确性能指标 收集GC日志 分析内存分布 调整JVM参数 验证效果
回答框架:从问题定义→数据采集→根因定位→参数调整→验证闭环,展示系统性调优能力。

面试问题:JVM内存分区有哪些?各自作用是什么?

考察点:JVM运行时数据区划分、线程共享/私有特性、各区域存储内容,以及OOM对应区域。

回答框架:先明确分区→分别说明用途→指出区域与OOM的对应关系→结合调优举例。

示例回答:JVM内存分堆、方法区、虚拟机栈、本地方法栈和程序计数器。堆存对象实例,方法区存类信息、常量,栈存局部变量。堆和方法区线程共享,栈和PC线程私有。堆溢出多调整-Xmx,栈溢出增加-Xss。

可能追问:1. Java 8之后元空间替换了永久代,为什么要换?2. 字符串常量池在哪里?

避坑提醒:不要混淆堆和栈的作用;注意JDK版本差异(如永久代改为元空间)。

面试问题:常见的GC算法有哪些?CMS和G1的区别?

考察点:GC算法原理、垃圾收集器特性、适用场景、停顿时间与吞吐量的权衡。

回答框架:先列举算法→对比收集器→突出CMS与G1的核心差异(目标、内存布局、停顿模型)。

示例回答:标记-清除、标记-复制、标记-整理。CMS以低停顿为目标,使用标记-清除,可能产生碎片;G1面向大堆,将堆分Region,可预测停顿,整理阶段无碎片。低延迟选G1,吞吐量优先选Parallel。

可能追问:1. G1的Mixed GC如何选择CSet?2. CMS并发阶段如何解决三色标记问题?

避坑提醒:CMS只在老年代收集,G1全堆;G1年轻代回收和Mixed GC并存。不要混淆配置参数-XX:+UseConcMarkSweepGC和-XX:+UseG1GC。

面试问题:如何进行内存泄漏排查?

考察点:内存泄漏常见原因、监控与工具(jstat、jmap、MAT)、泄漏分析流程。

回答框架:先检测异常(GC频繁/OOM)→生成Heap Dump→分析Dominator Tree→定位泄漏对象→追溯代码。

示例回答:用jstat观察Old区持续增长,jmap dump堆,MAT查看大对象和GC Root路径。如HashMap缓存未清除导致泄漏,则改为WeakHashMap或设置上限。线上可用Arthas实时监控。

可能追问:1. 静态集合类为什么容易泄漏?2. 使用软引用和弱引用的区别及适用场景?

避坑提醒:生产环境dump前触发Full GC避免误判;MAT的支配树和入站引用要分清。不要在示例中提“maybe”之类的模糊词。


项目案例:高并发订单系统JVM调优实践

S: 高并发订单系统 日均1亿+请求 T: 降低GC停顿 要求<30ms A: 调整G1参数 优化Region和IHOP R: 停顿降80% P99 25ms
业务背景电商大促期间,订单系统每秒峰值10万请求,出现频繁Stop-The-World,RT飙升。
规模指标日订单量1亿+,QPS 8~10万,堆内存256GB(单机),GC停顿最高达500ms。
技术栈JDK 11, G1 GC, Prometheus + Grafana, 自研APM, Arthas
核心难点大堆下G1的Region数过多(~2048),IHOP阈值不合理导致并发回收失败。
面试高频追问:1. 为什么选择G1而不是CMS?2. 你是如何确定-XX:G1HeapRegionSize的?3. 调优过程中如何回溯验证参数效果?
可迁移回答话术:“面对高频GC问题,我先通过GC日志定位Mixed GC频率异常,再用jstat监控Old区占用,发现IHOP过早触发。于是调整-XX:InitiatingHeapOccupancyPercent=45,同时将G1HeapRegionSize设为2MB减少Region数。最终P99 GC停顿从120ms降至25ms。这套方法同样适用于其他大堆低延迟场景。”