輕巧的執行緒堆疊檢視工具HotThreads
定位效能問題,尤其是cpu使用率過高時,經常需要查詢cpu消耗較高的執行緒,然後檢視其堆疊,從而進入程式碼定位問題。
該場景下, jstack+top是一種非常經典的方式。
jstack+top
jstack+top的一般套路:
1、top -H 檢視cpu佔用較高的執行緒,記錄十進位制的執行緒id
2、jstack 將執行緒資訊dump到檔案中,在檔案中根據執行緒id查詢該執行緒的堆疊。 注意,jstack輸出中執行緒id是16進位制的,這裡要做一次進位制轉換。
3、研究這個執行緒的堆疊
jstack+top方法的不足:
1、麻煩。由於top工具輸出是實時變化的,一般需要抓多次,重複下來,上述過程更顯繁瑣。
2、執行緒狀態時刻變動,top -H時看到一個執行緒的cpu佔用率較高,等到jstack 時可能已經處於sleep狀態,因此上述操作需要較高的APM
有什麼辦法能省卻這些麻煩 —— 能在看到執行緒堆疊的時候,直接看到他們各自的cpu佔用率呢? —— Hot Threads 可以!
Hot Threads
Hot Threads是一個小巧的開源工具,使用十分容易:
1、下載jar包,扔到伺服器上
2、執行java -jar HotThread.jar [pid] 即可,pid是被測的程式號。使用中注意填對路徑即可。
Hot Threads的輸出:
執行完上述指令後,Hot Threads會在很短時間內,重複查詢10次執行緒堆疊資訊(呼叫sun.management.ThreadImpl.getThreadInfo方法),統計平均cpu佔用最高的3個執行緒,列印執行緒堆疊,並顯示cpu佔用率。
106.3% CPU Usage by Thread `Swing-Shell`
10/10 snapshots sharing following 10 elements
sun.awt.shell.Win32ShellFolder2.getAttributes0(Native Method)
sun.awt.shell.Win32ShellFolder2.access$600(Unknown Source)
sun.awt.shell.Win32ShellFolder2$6.call(Unknown Source)
sun.awt.shell.Win32ShellFolder2$6.call(Unknown Source)
java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
java.util.concurrent.FutureTask.run(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
sun.awt.shell.Win32ShellFolderManager2$ComInvoker$3.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
1.6% CPU Usage by Thread `RMI TCP Connection(9)-172.30.41.210`
10/10 snapshots sharing following 32 elements
sun.management.ThreadImpl.getThreadInfo0(Native Method)
sun.management.ThreadImpl.getThreadInfo(Unknown Source)
sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
com.sun.jmx.mbeanserver.ConvertingMethod.invokeWithOpenReturn(Unknown Source)
com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(Unknown Source)
com.sun.jmx.mbeanserver.MXBeanIntrospector.invokeM2(Unknown Source)
com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(Unknown Source)
com.sun.jmx.mbeanserver.PerInterface.invoke(Unknown Source)
com.sun.jmx.mbeanserver.MBeanSupport.invoke(Unknown Source)
javax.management.StandardMBean.invoke(Unknown Source)
com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(Unknown Source)
com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.doOperation(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.access$200(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(Unknown Source)
javax.management.remote.rmi.RMIConnectionImpl.invoke(Unknown Source)
sun.reflect.GeneratedMethodAccessor21.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
sun.rmi.transport.Transport$1.run(Unknown Source)
java.security.AccessController.doPrivileged(Native Method)
sun.rmi.transport.Transport.serviceCall(Unknown Source)
sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
0.0% CPU Usage by Thread `Reference Handler`
10/10 snapshots sharing following 3 elements
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
|
上圖中,每個執行緒的能看到 10/10 標記。 n / m 意味著m次統計中,有n次都是該排名。
Hot Threads使用中的問題和解決方法:
直接執行java -jar HotThread.jar [pid]可能會報錯,此時可以換一種啟動方式:
java -classpath “/opt/jdk1.6/lib/tools.jar:HotThread.jar” hotthread.Main [pid]
其中 /opt/jdk1.6/lib/tools.jar 是伺服器上jdk tools包的完整路徑,hotthread.Main 是Hot Threads程式的入口。
Hot Threads的不足:
使用中發現,Hot Threads自身的cpu開銷比較高,有時候統計顯示cpu使用率第一的執行緒,在執行的是獲取執行緒資訊的操作,該條堆疊對分析問題無效。
2723.0% CPU Usage by Thread `RMI TCP Connection(4)-192.168.164.87`
6/10 snapshots sharing following 33 elements
sun.management.ThreadImpl.getThreadInfo1(Native Method)
sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:154)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
總結:
Hot Threads使用快速輕巧, 在需要使用jstack + top的場合,都可以嘗試代替比較繁瑣的jstack + top。
最新內容請見作者的GitHub頁:http://qaseven.github.io/
相關文章
- 根據openGauss/MogDB的lwtid檢視執行緒堆疊執行緒
- Java多執行緒-程式執行堆疊分析Java執行緒
- 分享一款JVM執行緒堆疊線上分析工具JVM執行緒
- 如何利用執行緒堆疊定位問題執行緒
- JVM 執行緒堆疊分析過程詳解JVM執行緒
- 如何抓取Thread Dump(轉儲執行緒堆疊)thread執行緒
- 怎樣在程式中獲取所有執行緒的堆疊資訊?執行緒
- 檢視執行緒所在模組執行緒
- [JVM工具(1)] 堆疊檢查利器jstat的使用JVMJS
- UNIX如何檢視執行緒執行情況執行緒
- Centos檢視程式的執行緒數量CentOS執行緒
- 執行緒轉儲:命名你的執行緒和檢視系統(轉)執行緒
- 如何優雅地檢視 JS 錯誤堆疊?JS
- 瞭解Javascript中的執行上下文和執行堆疊JavaScript
- linux 檢視 程式 執行緒數Linux執行緒
- windows下檢視oracle 執行緒 (session)WindowsOracle執行緒Session
- Linux下多執行緒檢視工具(pstree、ps、pstack)Linux執行緒
- 嘗試寫個UC瀏覽器(堆疊檢視A)瀏覽器
- JavaScript的工作原理:引擎,執行時和呼叫堆疊JavaScript
- Java併發(三)----建立執行緒的三種方式及檢視程式執行緒Java執行緒
- 檢視cpu是否開啟超執行緒執行緒
- 檢視和診斷JVM執行緒資訊JVM執行緒
- linux檢視是否開啟超執行緒Linux執行緒
- 解讀 JavaScript 之引擎、執行時和堆疊呼叫JavaScript
- 【Java多執行緒】輕鬆搞定Java多執行緒(二)Java執行緒
- PHP-stacktrace: PHP 程式外檢視函式呼叫堆疊PHP函式
- JavaScript中的執行上下文和堆疊是什麼JavaScript
- 聊一聊JavaScript中的執行上下文和堆疊JavaScript
- [譯] JavaScript 如何工作:對引擎、執行時、呼叫堆疊的概述JavaScript
- JavaScript是如何工作的:引擎,執行時和呼叫堆疊的概述!JavaScript
- 【譯】JavaScript的工作原理:引擎,執行時和呼叫堆疊的概述JavaScript
- 巧用Grafana和Arthas自動抓取K8S中異常Java程式的執行緒堆疊GrafanaK8SJava執行緒
- [Android開源]:一款安全、輕巧、簡單的執行緒池管理器EasyThreadAndroid執行緒thread
- JavaScript 工作原理之一-引擎,執行時,呼叫堆疊(譯)JavaScript
- Linux檢視某個程式的執行緒的3種方法Linux執行緒
- 如何檢視CPU核數和執行緒數?CPU的核心數、執行緒數的關係和區別執行緒
- 檢視正在執行的SQLSQL
- 使用jstack檢視當前程序全部執行緒的狀態JS執行緒