一个后端项目会起多个线程进行数据处理然后入库,发现某个表的数据不更新了,于是想到了线程可能阻塞了,查看日志发现了报了一个oom:GC overhead limit exceeded
,查询了一下这个oom的定义:当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.OutOfMemoryError:GC overhead limit exceeded 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。按照如下思路排查 查看进程内存和cpu使用状态,ps -ef查看java进程pid 为1查看java进程内各个线程的使用情况,top -Hp 加进程Id
,现场没有保存,可以看到几个线程确实占了很大的cpu
比如线程6占用cpu或者内存更高,需要查看此线程的堆栈,使用jstack pid命令查看当前java进程的堆栈状态在top命令中,已经获取到了占用cpu资源较高的线程pid,将该pid转成16进制的值每个线程都有一个nid,找到对应的nid即可,根据这个nid查看线程状态,RUNNABLE,线程处于执行中;BLOCKED,线程被阻塞WAITING,线程正在等待没有进一步分析,通过堆栈信息显示了有问题代码的行数
代码里有一处死循环,里面起了几个新线程,要等子线程返回结果再执行主线程,可能是每次都new一个list一起的,每次执行完手动执行一下list.clear()确实没再出现过这个oom