B、 jstack
jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:
1 | jstack [option] pid |
2 | jstack [option] executable core |
3 | jstack [option] [server- id @]remote- hostname -or-ip |
现实企业级开发中,有时候我们会碰到下面这些问题:
-
OutOfMemoryError,内存不足
-
内存泄露
-
线程死锁
-
锁争用(Lock Contention)
-
Java进程消耗CPU过高
jstat:一个极强的监视VM内存工具。可以用来监视VM内存内的各种堆和非堆的大小及其内存使用量。
jmap:打印出某个java进程(使用pid)内存内的所有'对象'的情况(如:产生那些对象,及其数量)。
本文部分转自https://www.cnblogs.com/rainy-shurun/p/5732341.html
Linux使用jstat命令查看jvm的GC情况
命令格式
jstat命令命令格式:
参数说明:
示例说明
示例
结果说明
jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。
第一步先找出Java进程ID,我部署在服务器上的Java应用名称为mrf-center:
1 | root@ubuntu:/ # ps -ef | grep mrf-center | grep -v grep |
2 | root 21711 1 1 14:47 pts/3 00:02:10 java -jar mrf-center.jar |
得到进程ID为21711,第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我这里用第三个,输出如下:
TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为21742的线程
得到21742的十六进制值为54ee,下面会用到。
OK,下一步终于轮到jstack上场了,它用来输出进程21711的堆栈信息,然后根据线程ID的十六进制值grep,如下:
1 | root@ubuntu:/ # jstack 21711 | grep 54ee |
2 | "PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000] |
可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),我找了下我的代码,定位到下面的代码:
01 | // Idle wait |
02 | getLog().info( "Thread [" + getName() + "] is idle waiting..." ); |
03 | schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting; |
04 | long now = System.currentTimeMillis(); |
05 | long waitTime = now + getIdleWaitTime(); |
06 | long timeUntilContinue = waitTime - now; |
07 | synchronized (sigLock) { |
08 | try { |
09 | if (!halted.get()) { |
10 | sigLock.wait(timeUntilContinue); |
11 | } |
12 | } |
13 | catch (InterruptedException ignore) { |
14 | } |
15 | } |