予枫个人主页 个人专栏: 《Java 从入门到起飞》《读研码农的干货日常》《Java 面试刷题指南》 Debug 这个世界Return 更好的自己线上服务突然卡顿、CPU飙升到100%、日志报OOM崩溃、频繁Full GC导致服务不可用作为Java后端JVM调优是必备技能尤其是CPU飙升、OOM、频繁Full GC这三类高频场景题既是工作刚需也是面试官重点考察内容。本文结合实战场景拆解排查流程、工具用法附面试追问新手也能快速上手彻底搞定JVM调优痛点文章目录一、JVM调优排查前准备工具环境1.1 核心排查工具必装1.2 排查前必确认的信息二、CPU飙升问题排查实战高频场景2.1 排查流程一步到位2.2 具体操作步骤附命令2.3 常见原因及解决方案2.4 面试官追问环节高频考点三、OOM内存溢出问题排查实战致命场景3.1 排查核心前提3.1.1 生成堆转储文件两种方式3.1.2 分析堆转储文件使用MAT工具3.2 常见OOM类型及排查方案3.2.1 堆内存溢出最常见3.2.2 元空间溢出3.2.3 栈内存溢出3.3 面试官追问环节高频考点四、频繁Full GC问题排查实战性能瓶颈4.1 排查流程4.2 具体操作步骤4.3 常见原因及解决方案4.4 面试官追问环节高频考点五、总结一、JVM调优排查前准备工具环境调优排查的核心是“精准定位”而非盲目调参先准备好必备工具才能高效排查问题避免手忙脚乱。1.1 核心排查工具必装JDK自带工具无需额外安装最常用jps、jstack、jmap、jstat、jinfo可视化工具提升效率JVisualVMJDK自带、MATMemory Analyzer Tool分析OOM日志、Arthas阿里开源线上排查神器系统工具top查看CPU占用、free查看内存、df查看磁盘、netstat查看网络提示线上环境优先使用命令行工具jstack、jstat等避免可视化工具占用过多系统资源测试环境可使用JVisualVM、MAT进行详细分析。觉得有用的话点赞收藏避免后续找不到1.2 排查前必确认的信息服务当前运行状态是否卡顿、是否报错、QPS是否异常JVM启动参数堆内存、元空间大小、垃圾收集器配置等系统资源使用情况CPU、内存、磁盘、网络问题出现的时间、频率突发还是持续、是否和业务峰值相关二、CPU飙升问题排查实战高频场景CPU飙升是线上最常见的JVM相关问题表现为服务卡顿、响应变慢top命令查看CPU占用率Java进程占比远超其他进程。2.1 排查流程一步到位2.2 具体操作步骤附命令查看CPU占用最高的进程top找到Java进程进程名含java记录PID假设为12345。查看进程内CPU最高的线程top -Hp 12345记录线程ID假设为12346。线程ID转换为十六进制jstack输出的线程ID是十六进制printf %x\n 12346假设结果为303a。查看线程栈信息定位问题代码jstack 12345 | grep 303a -A 30。2.3 常见原因及解决方案常见原因典型表现解决方案死循环/无限循环线程栈显示某段代码持续执行无退出条件排查循环逻辑添加退出条件修复代码频繁GCYoung GC/Full GCjstat查看GC频率极高GC时间长调整堆内存大小、优化垃圾收集器、减少大对象创建锁竞争synchronized/lock线程栈显示多个线程阻塞在锁上BLOCKED状态减少锁粒度、使用无锁结构ConcurrentHashMap、避免死锁频繁反射/序列化线程栈显示大量反射相关方法调用缓存反射结果、避免频繁序列化使用高效序列化框架如Protobuf实战案例线上服务CPU飙升到100%通过jstack排查发现某接口存在死循环循环条件错误导致无限执行修复循环条件后CPU占用恢复正常。2.4 面试官追问环节高频考点Q1CPU飙升时除了jstack还能用到哪些工具如何快速区分是代码问题还是GC问题A还可以用Arthas的thread命令直接查看高CPU线程、jstat -gcutil PID 1000 10查看GC频率区分方法若GC频率高、GC时间长如Young GC每秒几次则是GC问题否则是代码问题死循环、锁竞争等。Q2为什么死循环会导致CPU飙升JVM对此有什么机制可以缓解吗A死循环会让线程一直占用CPU核心无法释放导致CPU利用率拉满JVM没有主动缓解机制只能通过排查代码修复可通过线程监控工具如Arthas及时发现异常线程。三、OOM内存溢出问题排查实战致命场景OOMOutOfMemoryError是致命问题表现为服务直接崩溃日志中会出现java.lang.OutOfMemoryError常见类型有堆内存溢出、元空间溢出。3.1 排查核心前提OOM排查的关键是获取堆转储文件heap dump通过分析堆转储文件定位内存泄漏或大对象从而找到问题根源。3.1.1 生成堆转储文件两种方式启动时配置参数推荐线上提前配置# 当发生OOM时自动生成堆转储文件保存到指定路径-XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath/usr/local/logs/heapdump.hprof线上已发生OOM手动生成服务未完全崩溃时jmap-dump:formatb,file/usr/local/logs/heapdump.hprof12345PID3.1.2 分析堆转储文件使用MAT工具下载MAT工具Eclipse官网可下载打开堆转储文件.hprof。查看「Leak Suspects」内存泄漏可疑点定位内存泄漏的对象。查看对象的引用链找到导致对象无法被GC回收的原因如静态集合持有对象引用、长生命周期对象持有短生命周期对象。3.2 常见OOM类型及排查方案3.2.1 堆内存溢出最常见日志特征java.lang.OutOfMemoryError: Java heap space常见原因大对象创建过多如大量List、Map存储数据、内存泄漏、堆内存配置过小。解决方案临时方案调大堆内存-Xms2g -Xmx2g根据服务器配置调整。根本方案排查内存泄漏通过MAT分析引用链、优化代码避免创建大量大对象、及时释放无用引用。3.2.2 元空间溢出日志特征java.lang.OutOfMemoryError: Metaspace常见原因大量动态生成类如反射、CGLIB代理、元空间配置过小JDK8元空间默认无上限但若手动配置过小会溢出。解决方案调大元空间-XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m。减少动态生成类的数量缓存动态生成的类。3.2.3 栈内存溢出日志特征java.lang.StackOverflowError本质是栈内存溢出常被归为OOM相关问题常见原因递归调用过深、栈内存配置过小。解决方案优化递归逻辑改为迭代、调大栈内存-Xss1m默认1m根据需求调整。提示堆转储文件可能较大几十MB到几GB线上生成时注意磁盘空间避免占满磁盘觉得有帮助记得点赞支持后续持续更新JVM实战技巧~3.3 面试官追问环节高频考点Q1堆内存溢出和内存泄漏的区别是什么如何判断是内存泄漏还是内存不足A区别内存泄漏是对象无法被GC回收导致内存逐渐耗尽内存不足是堆内存配置过小无法满足业务需求。判断方法若堆转储文件中存在大量未被使用但无法回收的对象引用链完整则是内存泄漏若对象都是正常使用的只是堆内存不够则是内存不足。Q2JDK8中永久代被元空间替代元空间和永久代的区别是什么为什么要替换A区别1. 存储位置永久代在堆内存中元空间在本地内存中2. 内存限制永久代有固定大小默认几十MB元空间默认无上限受本地内存限制。替换原因永久代大小难以调整容易出现OOM元空间使用本地内存避免了永久代的内存限制问题同时减少了GC对永久代的回收压力。四、频繁Full GC问题排查实战性能瓶颈频繁Full GC表现为服务卡顿、响应延迟增加Full GC执行频率高如每分钟几次每次Full GC耗时过长如超过1秒导致服务不可用。4.1 排查流程发现频繁Full GCjstat -gcutil PID 1000 10 查看GC统计判断Full GC原因内存不足/内存泄漏/GC参数不合理生成堆转储文件分析内存使用情况优化GC参数/修复内存泄漏/调整堆内存验证Full GC频率是否降低4.2 具体操作步骤查看GC统计信息确认Full GC频率和耗时# 每1000毫秒输出一次GC统计共输出10次jstat-gcutil12345100010关键指标FGCFull GC次数、FGCTFull GC总耗时若FGC频繁如每分钟≥1次、FGCT≥1秒说明存在问题。分析Full GC原因若堆内存使用率接近100%说明堆内存不足需调大堆内存。若堆内存使用率不高但仍频繁Full GC可能是内存泄漏对象无法回收需通过MAT分析堆转储文件。若GC参数不合理如老年代太小、垃圾收集器选择不当需调整GC参数。4.3 常见原因及解决方案常见原因解决方案老年代内存不足调大堆内存-Xmx、调整老年代比例-XX:NewRatio2老年代:年轻代2:1内存泄漏排查代码释放无用引用如静态集合清理、监听器注销大对象直接进入老年代调整年轻代大小-Xmn让大对象先在年轻代回收避免直接进入老年代垃圾收集器选择不当并发场景使用G1收集器-XX:UseG1GC高吞吐量场景使用ParallelGC实战案例线上服务频繁Full GC每分钟3-4次通过jstat排查发现老年代内存使用率高达98%调大堆内存从1g调整为2g并调整G1收集器参数后Full GC频率降至每小时1次以内服务卡顿问题解决。4.4 面试官追问环节高频考点Q1频繁Full GC和频繁Young GC的区别是什么各自的影响是什么A区别Young GC发生在年轻代Eden区、Survivor区回收年轻代垃圾耗时短几十毫秒对服务影响小Full GC发生在整个堆年轻代老年代元空间回收全堆垃圾耗时长几百毫秒到几秒会导致服务卡顿。影响频繁Young GC会导致服务响应变慢频繁Full GC会导致服务卡顿甚至不可用。Q2G1收集器如何避免频繁Full GC如果G1仍出现频繁Full GC该如何优化AG1通过分区回收、动态调整分区大小优先回收垃圾多的分区减少Full GC的发生若G1仍频繁Full GC优化方案1. 调大堆内存-Xmx2. 调整G1的停顿时间目标-XX:MaxGCPauseMillis2003. 调整初始堆内存-Xms避免堆内存频繁扩容4. 排查内存泄漏。五、总结JVM调优实战的核心是“先定位问题再优化解决”而非盲目调参。CPU飙升、OOM、频繁Full GC这三类场景排查思路可总结为借助工具jstack、jmap、jstat、MAT、Arthas获取关键信息线程栈、堆转储、GC统计定位问题根源代码问题/内存问题/GC参数问题针对性优化修复代码/调整JVM参数/清理内存泄漏验证优化效果避免二次问题。本文覆盖了实战排查流程、工具用法、常见问题及面试追问适合Java后端开发、运维人员学习也可作为面试备考资料。记住JVM调优没有固定模板需结合业务场景和服务器配置灵活调整多实战、多总结才能真正掌握调优技巧。作者予枫CSDN技术博主专注Java后端、JVM调优、性能优化实战分享关注我解锁更多实战技巧欢迎在评论区留言分享你的JVM调优踩坑经历~