1. 缘由
一台线上机器内存耗尽,OOM 导致服务注册的 Mesh 客户端被干掉了,大量服务调用异常。运维同事查看机器负载,发现我们组内一个Java 服务占用的内存有点异常,启动命令-Xmx128m
指定了最大堆内存只有 128M,但是整个进程占用的内存达到了 640M,显然是有问题的
2. 线上排查
运维截图一扔,锅是甩不掉的,老老实实登录到线上机器排查。内存占用过高首先想到的就是发生了内存泄露
,使用 Jmap -histo $pid > heap.log
输出堆内对象统计情况到文件中,查看文件发现堆中占用内存最多的是各种数组,没有发现明显的问题。没法子,使用 top -H p $pid
命令检查该进程内运行的线程状况,终于发现了可疑点,在这个Java 服务里面运行的子线程居然有 5000 个,并且几乎全部都在 Sleeping 状态
这种情况首先想到的是发生了线程死锁,资源争用导致大量线程被阻塞了。使用 jstack -l $pid > stack.log
将线程栈相关状况输出到文件中,打开文件一搜索却大失所望,根本没有死锁发生。线程状态大都在 TIMED_WAITING
,不过随着一行行往下看,也发现了一个可疑点,以下这种 OkHttp ConnectionPool
的线程出现得太多了,线程序号甚至达到了1082707
"OkHttp ConnectionPool" #1082707 daemon prio=5 os_prio=0 tid=0x00007f564c18f000 nid=0x1a4d in Object.wait() [0x00007f5602cb4000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:460) at okhttp3.ConnectionPool$1.run(ConnectionPool.java:67) - locked <0x00000000fc30fb30> (a okhttp3.ConnectionPool) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Locked ownable synchronizers: - <0x00000000fc305f98> (a java.util.concurrent.ThreadPoolExecutor$Worker)
标签:JAVA,占用,ConnectionPool,排查,线程,内存,java,ThreadPoolExecutor From: https://www.cnblogs.com/chenghening/p/16799465.html