-
使用top 命令观察问题:比如内存不断增长,CPU占用率居高不下。
-
使用top -Hp pid(进程号) 观察进程中的线程,哪个线程CPU和内存占比高。
-
使用 jps 命令可以列出当前系统下所有运行的Java进程。
-
使用 jstack 命令 定位线程的堆栈 ,示例图如下,
重点关注线程状态java.lang.Thread.State死锁,Deadlock(重点关注)
执行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked这里有个排查多线程死锁的方法:
线程堆栈中的parking to wait for <0x00000000ff810688> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) 代表当前线程正在等待<0x00000000ff810688>这个对象资源,就是等待这个对象的锁释放,比如有很多线程都在等待这把锁,拿着<0x00000000ff810688>这个对象去jstack dump出来的信息找,找到持有<0x00000000ff810688>这个对象的线程,并且状态是Runnable的,就说明是这个线程一直占用这把锁没有释放。(这只有一个简单的方法,具体问题还是要具体分析的)
-
使用 jmap - histo pid(进程号)示例图如下, 命令查看有多少对象产生,哪个类产生的对象占用内存 最大。
也可以使用 jmap -dump:format=b,file=xxx pid (注意:线上环境尽量别使用,如果堆内存特别大的话,jmap执行期间会对进程产生很大影响,占用CPU资源,造成系统卡顿,可以配置参数-XX:+HeapDumpOnOutOfMemoryError,OOM的时候会自动产生堆转储文件)
来把堆的转储文件给dump到文件中,然后具体分析。使用MAT ,jhat,jvisualvm 等工具去进行具体分析
MAT的使用:https://blog.csdn.net/a5552157/article/details/109204255
jhat的使用:https://www.cnblogs.com/baihuitestsoftware/articles/6406271.html
jvisualvm 是在java的安装目录bin下面的工具
最后推荐一个功能非常强大JVM诊断工具:阿里的Arthas https://gitee.com/arthas/arthas