Linux服务器Java 1.8应用报java.lang.OutOfMemoryError如何排查
排查Java堆内存溢出的Linux Shell工具及使用方法
一、JDK内置原生工具(无需额外安装,适配Java 1.8)
jps
用于快速获取目标Java应用的进程ID(PID),是所有排查操作的第一步,执行命令:
输出结果中会展示所有Java进程的主类全路径、启动参数、PID,直接匹配你的Web应用名称即可拿到对应PID。jps -lvmjcmd(Java 1.8优先推荐,性能影响更小)
实时统计堆内存中所有存活对象的占用排名,执行命令:
输出结果会按类的总占用内存从高到低排序,直接可以看到占内存最高的前50个类、实例数量、总占用字节数,可快速定位是否存在大量未释放的数据库结果集、大集合对象等。jcmd <替换为实际PID> GC.class_histogram | head -50jmap- 快速查看全量对象内存统计(包含待回收对象):
jmap -histo <替换为实际PID> | head -50- 导出完整堆转储文件用于深度分析,执行命令:
*注意:导出堆转储时会短暂暂停应用响应,建议在业务低峰期执行,可加jmap -dump:format=b,file=/tmp/heap_dump.hprof <替换为实际PID>live参数仅导出存活对象,减少文件体积和暂停时长:jmap -dump:live,format=b,file=/tmp/heap_dump_live.hprof <PID>jstat
持续监控GC回收情况,确认内存泄漏特征,执行命令:
该命令表示每秒输出一次GC统计结果,共输出20次,可查看新生代、老年代的占用率,Young GC、Full GC的频率和耗时,如果老年代占用率持续上涨、Full GC后占用率没有明显下降,即可确认存在内存泄漏。jstat -gcutil <替换为实际PID> 1000 20jhat
可在Shell端直接解析堆转储文件并启动HTTP服务查看分析结果,执行命令:
执行后访问服务器IP的7000端口即可查看堆内存的详细分析结果,包含各个类的引用链、对象占用情况。jhat -port 7000 /tmp/heap_dump.hprof
二、Linux系统级辅助工具
top
查看Java进程的整体资源占用以及内部线程的资源排名,执行命令:
输出结果中可以看到该进程下所有线程的CPU、内存占用率,将占用高的线程ID转为16进制后可和top -p <替换为实际PID> -Hjstack的线程栈结果对应,定位到具体的业务方法。pmap
查看Java进程的内存段分布,辅助确认内存占用的结构,执行命令:
输出按内存占用从高到低排序的内存段列表,可辅助排除堆外内存占用的干扰。pmap -x <替换为实际PID> | sort -n -k3 | tail -20
三、场景优化建议
由于你的应用是数据库操作类Web应用,偶发堆内存溢出大概率是未分页的全表查询、大量数据库连接未释放、大对象长期持有未回收导致,建议在JVM启动参数中添加以下配置,OOM发生时自动导出堆转储,无需蹲点监控:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap_oom.hprof
内容的提问来源于stack exchange,提问作者willberthos
相关产品推荐
相关产品推荐

