JVM调优定位最耗cpu的线程

JVM调优定位最耗cpu的线程
jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有 ps、top、printf、jstack、grep

第一步先找出Java进程ID

可以通过 jps 或 ps -ef|grep java找到 java进程;
[root@redis webapps]# jps
2403 NameNode
22272 Bootstrap
17019 Jps

得到进程ID为22272

第二步找出该进程内最耗费CPU的线程

可以使用
1)ps -Lfp pid
2)ps -mp pid -o THREAD, tid, time
3)top -Hp pid
用第三个,输出如下:

[root@redis webapps]# top -Hp 22272
top - 10:09:30 up 9 days, 22:10,  1 user,  load average: 0.00, 0.00, 0.00
Tasks:  30 total,   0 running,  30 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   3923196k total,  3795588k used,   127608k free,   153056k buffers
Swap:  6160376k total,        0k used,  6160376k free,  3079244k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                
22272 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                                                                                    
22278 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                    
22279 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                   
22282 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                    
22283 root      20   0 2286m 122m  11m S  0.0  3.2   3:01.48 java                                                                                    
22287 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                    
22288 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                    
22289 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java                                                                                    
22290 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.03 java                                                                                    
22291 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.34 java                                                                                    
22292 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.06 java                                                                            
22299 root      20   0 2286m 122m  11m S  0.0  3.2   0:06.37 java                                                                                    
22301 root      20   0 2286m 122m  11m S  0.0  3.2   1:09.73 java                                                                                    
17034 root      20   0 2286m 122m  11m S  0.0  3.2   0:00.00 java

TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为22283 的线程

第三步获取线程id的十六进制码

用 printf “%x\n” 22283
[root@redis webapps]# printf ‘%x\n’ 22283
570b
得到22283 的十六进制值为570b。

第四步使用jstack获取堆栈信息

下一步轮到jstack上场了,它用来输出进程22272 的堆栈信息,然后根据线程ID的十六进制值grep,如下:
[root@redis webapps]# jstack 22272 | grep 570b
“SchedulerThread” prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait()

可以看到CPU消耗在SchedulerThread这个类的Object.wait(),定位到下面的代码:

// Idle wait
synchronized(sigLock) {
  try {
    if(!halted.get()) {
      sigLock.wait(timeUntilContinue);
    }
  } 
  catch (InterruptedException ignore) {
  }
}

它是轮询任务的空闲等待代码,上面的sigLock.wait(timeUntilContinue)就对应了前面的Object.wait()。
也可以通过 jstack导出所有堆栈信息,根据线程ID的十六进制值找到该线程的堆栈信息,通过该信息分析其使用情况。

你可能感兴趣的:(JVM)