JVM调优之jstack找出最耗cpu的线程并定位代码
jstack可以定位到線程堆棧,根據堆棧信息我們可以定位到具體代碼,所以它在JVM性能調優中使用得非常多。下面我們來一個實例找出某個Java進程中最耗費CPU的Java線程并定位堆棧信息,用到的命令有ps、top、printf、jstack、grep。
第一步先找出Java進程ID,服務器上的Java應用名稱為mrf-center:
root@ubuntu:/# ps -ef | grep mrf-center | grep -v grep root 21711 1 1 14:47 pts/3 00:02:10 java -jar mrf-center.jar 得到進程ID為21711,第二步找出該進程內最耗費CPU的線程,可以使用 1)ps -Lfp pid--替換你的進程id 2)ps -mp pid -o THREAD, tid, time 3)top -Hp pid--替換你的進程id top -Hp pid 輸出信息的含義: -Hp “H”的解釋:如果輸入大寫P,則結果按CPU占用降序排序。如果輸入大寫M,結果按內存占用降序排序。H是打開或者關閉顯示線程信息的開關。 但是顯示如下: [root@sncdpreweb04 ~]# top -p 6766 top - 15:54:36 up 261 days, 23:18, ?1 user, ?load average: 11.95, 13.60, 14.16 Tasks: ?26 total, ? 2 running, ?24 sleeping, ? 0 stopped, ? 0 zombie Cpu(s): 96.8%us, ?3.1%sy, ?0.0%ni, ?0.0%id, ?0.0%wa, ?0.0%hi, ?0.0%si, ?0.1%st Mem: ? 8059780k total, ?5821348k used, ?2238432k free, ? ?65636k buffers Swap: 10485752k total, ?2696164k used, ?7789588k free, ? 269240k cached ? PID USER ? ? ?PR ?NI ?VIRT ?RES ?SHR S %CPU %MEM ? ?TIME+ ?COMMAND ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 11136 root ? ? ?20 ? 0 5514m 1.3g ?10m R 37.0 16.5 ? 0:12.81 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6784 root ? ? ?20 ? 0 5514m 1.3g ?10m R 27.6 16.5 ? 4:09.61 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6785 root ? ? ?20 ? 0 5514m 1.3g ?10m S 27.0 16.5 ? 4:01.17 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6772 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?3.0 16.5 ? 0:15.53 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6770 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?2.0 16.5 ? 0:15.42 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6778 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?2.0 16.5 ? 0:15.58 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6777 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?1.7 16.5 ? 0:15.66 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6780 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.7 16.5 ? 0:09.25 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6828 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.7 16.5 ? 0:13.31 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6786 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.3 16.5 ? 0:41.63 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6766 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.00 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6769 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 8:59.85 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6781 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.22 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6782 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.26 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6783 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.00 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6787 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.00 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6788 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:01.93 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6820 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.00 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6823 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.00 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6824 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.02 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6825 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.03 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6826 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:01.28 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6827 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.10 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6829 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.05 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?6830 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.35 java ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?8915 root ? ? ?20 ? 0 5514m 1.3g ?10m S ?0.0 16.5 ? 0:00.00 java ?? 為什么 pid展示的是進程id,而且還有6766這個線程????The four threads will have the same PID but only when viewed from above. What you (as a user) call a PID is not what the kernel (looking from below) calls a PID.
In the kernel, each thread has it's own ID, called a PID (although it would possibly make more sense to call this a TID, or thread ID) and they also have a TGID (thread group ID) which is the PID of the thread that started the whole process.
Simplistically, when a new process is created, it appears as a thread where both the PID and TGID are the same (new) number.
When a thread starts another thread, that started thread gets its own PID (so the scheduler can schedule it independently) but it inherits the TGID from the original thread.
That way, the kernel can happily schedule threads independent of what process they belong to, while processes (thread group IDs) are reported to you.
翻譯: 四個線程將具有相同的PID,但僅在從上方觀察時。 您(作為用戶)調用PID不是內核(從下面看)調用PID。 在內核中,每個線程都有自己的ID,稱為PID(盡管將其稱為TID或線程ID可能更有意義),并且它們還具有作為線程的PID的TGID(線程組ID) 開始了整個過程。 簡單來說,當一個新進程被創建時,它顯示為一個線程,PID和TGID都是相同的(新的)數字。 當一個線程啟動另一個線程時,該線程獲得自己的PID(因此調度程序可以獨立調度),但它會從原始線程繼承TGID。 這樣,內核可以高興地安排線程,而不管它們屬于什么進程,而進程(線程組ID)則會報告給您。? ******************************************************************************************************************************************* 輸出信息解釋 ******************************************************************************************************************************************* (1)一前面兩行信息
TIME列就是各個Java線程耗費的CPU時間,CPU時間最長的是線程ID為21742的線程,用
printf "%x\n" 21742得到21742的十六進制值為54ee,下面會用到。
OK,下一步終于輪到jstack上場了,它用來輸出進程21711的堆棧信息,然后根據線程ID的十六進制值grep,如下:
root@ubuntu:/# jstack 21711 | grep 54ee "PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait()可以看到CPU消耗在PollIntervalRetrySchedulerThread這個類的Object.wait(),我找了下我的代碼,定位到下面的代碼:
// 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()。
總結
以上是生活随笔為你收集整理的JVM调优之jstack找出最耗cpu的线程并定位代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 带你分析sem和seo对优化的本质和利益
- 下一篇: surefire单元测试 并发 提速