定位Java程序内存使用过高或者内存泄漏的问题跟CPU也类似,一般可以分为以下3个步骤:
一、定位进程
通过 top -c
(然后按 Shift+M
按内存排序),或者 htop
等工具定位到具体的高内存进程。假设定位到的进程ID为14279。
二、定位线程
2.1 通过top查看线程
top -H -p 14279
(然后按 Shift+M
按内存排序)定位占内存的线程:
%Cpu(s): 0.5 us, 0.7 sy, 0.0 ni, 98.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 8168236 total, 231696 free, 3660496 used, 4276044 buff/cache KiB Swap: 969964 total, 969964 free, 0 used. 4197860 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14293 weiping 20 0 4508772 97036 18112 S 10 12 152:35.42 java 14279 weiping 20 0 4508772 97036 18112 S 5.0 1.2 0:00.00 java 14282 weiping 20 0 4508772 97036 18112 S 0.0 1.2 0:00.37 java
2.2 通过ps统计下当前进程的线程数
ps p 14279 -L -o pcpu,pmem,pid,tid,time,tname,cmd |wc -l
2.3 初步判断
通过以上二步确认是否线程开多了,还是单个线程内存占用过多导致。
2.4 查看线程信息
通过 thread tid
直接查看指定线程的堆栈信息:
[arthas@42436]$ thread 91 "MQ-AsyncTraceDispatcher-Thread-ce0ebd2a-5807-4053-ae3c-7472fe4b5aef" Id=91 TIMED_WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@774405a1 at sun.misc.Unsafe.park(Native Method) -- waiting on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@774405a1 at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) at java.util.concurrent.ArrayBlockingQueue.poll(ArrayBlockingQueue.java:418) at org.apache.rocketmq.client.trace.AsyncTraceDispatcher$AsyncRunnable.run(AsyncTraceDispatcher.java:238) at java.lang.Thread.run(Thread.java:748) Affect(row-cnt:0) cost in 2 ms.
更多官方详细文档: Arthas命令文档——thread
三、定位具体方法
3.1 通过jmap dump内存快照
如果是线上环境,注意dump之前必须先将流量切走,否则大内存dump是直接卡死服务。 ``` # dump当前快照 jmap -dump:live,format=b,file=dump.hprof <pid> # 触发full gc,然后再dump一次 jmap -dump:live,format=b,file=dump_gc.hprof <pid> ``` dump:live的作用是会触发Full GC,然后再dump数据,用作gc前后的数据做对比。
3.2 使用MAT分析
如果快照文件不大,可以下载到本地,然后通过 MAT 分析。
3.3 上传到fastthread.io分析
如果快照文件不大,也可以上传到 https://fastthread.io/ 分析。
3.4 通过jhat分析
如果快照文件很大,可以在服务器上直接分析:
faceless@ttg12:~/tmp$ jhat dump.hprof Reading from dump.hprof... Dump file created Mon Jun 22 14:33:00 CST 2020 Snapshot read, resolving... Resolving 36246 objects... Chasing references, expect 7 dots....... Eliminating duplicate references....... Snapshot resolved. Started HTTP server on port 7000 Server is ready.
分析完成后,访问 http://ttg12 :7000,如下图:
点进入看实例数(图来自网络,这里只是示意):
找到数量大的业务类,比如上图中是 Packet
。然后一路点进去,跟踪引用路径,看到底是哪个类引用的。
3.5 通过Arthas分析
TO BE FINISHED——也可以通过服务器上的Arthas分析。
原文
https://segmentfault.com/a/1190000022995307
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Java应用问题定位系列——内存占用过高