要使用jstack首先要有jdk环境,这个大家可以自行百度安装一下
第一步通过 ps -ef | grep XXX找出对应的服务的PID
可以多重嵌套使用ps命令
ps -ef | grep java | grep wms | grep 30010
得到进程ID为14007,第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我这里用第三个,输出如下:
TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为14038的线程,用
printf “%x\n” 14038
得到14038的十六进制值为36d6,下面会用到
OK,下一步终于轮到jstack上场了,它用来输出进程14038的堆栈信息,然后根据线程ID的十六进制值grep,如下:
root@ubuntu:/# jstack 14038| grep 36d6
“PollIntervalRetrySchedulerThread” prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]
可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),我找了下我的代码,定位到下面的代码:
[java] view plain copy
// Idle wait
getLog().info("Thread [" + getName() + "] is idle waiting...");
schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;
long now = System.currentTimeMillis();
long waitTime = now + getIdleWaitTime();
long timeUntilContinue = waitTime - now;
synchronized(sigLock) {
try {
if(!halted.get()) {
sigLock.wait(timeUntilContinue);
}
}
catch (InterruptedException ignore) {
}
}
它是轮询任务的空闲等待代码,上面的sigLock.wait(timeUntilContinue)就对应了前面的Object.wait()。