一次线上JVM进程OOM问题排查

问题描述

线上查询设计服务每运行一段时间就会抛oom异常,然后服务不可用,重启后恢复。

服务异常之前通过cat监控发现会频繁full gc,gc后释放内存很小,我们推断发生了内存泄漏。

相关工具:ps、jmap、mat、top、jps、jstack

解决步骤

(1)找到进程pid

由于已经知道哪个服务出了什么问提,跳过jps,top等步骤直接ps ps aux | grep panther-query

(2)查看推内存使用情况

jmap -heap pid

(3)查看内存实例占用情况

jmap -histo:live pid | more

定位到几个异常的类实例特别多,占用内存很大超过500MB

(4)生成dump文件

jmap -dump:live,format=b,file=data.dump pid

(5)使用mat分析dump

/path/ParseHeapDump.sh data.dump org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components

会生成三个zip文件 heap-dump_System_Overview.zip heap-dump_Leak_Suspects.zip heap-dump_Top_Components.zip

(6)解压zip后查看分析文档

主要分析Leak_Suspects找到可能会引起内存泄漏的点

(7)结合代码分析发现几处异常

7.1 StringBuilder char[] 问题:

频繁deleteCharAt 和append导致的扩容(array copy) 方案:new StringBuilder指定容量,默认16KB(16384),append只增不删(尽量避免使用deleteCharAt)

7.2 String[][] String 问题:

频繁创建10w行*n列大数组 方案:减少中间结果占用内存,直接ResultSet到Hdfs,取消使用大数组

7.3 FileSystem.Cache 问题:

内存泄漏,同时并持有的Configuration也没有释放,占用过高的内存 原因使用代理生成的ugi,每次都是new的,导致FileSystem每次都是new实例,代码里有没有close,所以泄露了 方案:FileSystem放入try catch块,自动close

(8)最后jvm参数配置oom时打印dump日志

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/project/heapdump.hprof

posted @ 2022-07-06 11:22  OUYM  阅读(109)  评论(0编辑  收藏  举报