-
找到java应用进程 ID即 java_id
-
找到该 java_id对应的CPU占用比较大的线程 ID即 thread_id
-
使用jdk自带jstack工具打印跟该线程相关的堆栈信息
[root@pvz-yrd-yirenbaonode-01 ~]# java_pid=`ps -ef|grep java|grep '^tomcat'|awk '{print $2}'`
[root@pvz-yrd-yirenbaonode-01 ~]# thread_pid=`ps -Leo pid,lwp,user,comm,pcpu --no-headers | grep "[ ]${java_pid}"|sort -rnk 5 |head -n 1|awk '{print $2}'`
[root@pvz-yrd-yirenbaonode-01 ~]# ox=`printf "%x" ${thread_pid}` ##16进制,
[root@pvz-yrd-yirenbaonode-01 ~]# su - tomcat -s /opt/yrd_soft/java/bin/jstack ${java_pid}|grep ${ox} -C 10 ## 这里因为是以tomcat用户启动,并且tomcat没有解释器权限,所以使用 su - tomcat -s
- parking to wait for <0x0000000781f18788> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"DubboServerHandler-xx.xx.xx.xx:20880-thread-1346" daemon prio=10 tid=0x00007f3291ae2800 nid=0x10d2 waiting on condition [0x00007f32269b0000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000781f18788> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
--
- locked <0x0000000781990b18> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
"ActiveMQ InactivityMonitor ReadCheckTimer" daemon prio=10 tid=0x00007f32b800e000 nid=0xae5 in Object.wait() [0x00007f328187e000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x00000007819eb550> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)
"Selector Worker: 0" daemon prio=10 tid=0x00007f32a8028800 nid=0xae2 runnable [0x00007f3281b81000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
- locked <0x00000007819eb358> (a sun.nio.ch.Util$2)
- locked <0x00000007819eb340> (a java.util.Collections$UnmodifiableSet)
- locked <0x0000000781c6ea60> (a sun.nio.ch.EPollSelectorImpl)
at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
at org.apache.activemq.transport.nio.SelectorWorker.run(SelectorWorker.java:93)
实际过程中如果确认是java导致cpu占用过高,其实最简单暴力的方法是:jstack $java_pid全部把堆栈打印出来,给开发看.
还有一种做法,是先把jstack打印出来,然后根据线程进行CPU占用排个序,比如打印cpu占用前十的线程的堆栈,等等.