好了我們這一篇繼續來說命令行監控指令,上一篇說了4個比較重要的指令,其中用的比較多的也就是jstat和jmap了。
jhat:
堆轉儲分析工具
他是JDK自帶的分析工具,分析我們上一篇說的jmap轉存的內存快照,??內置了一個微型的HTTP服務器提供Web界面瀏覽分析結果(默認端口是7000),幫助識別內存泄漏和大對象,?同時支持OQL(Object Query Language)查詢,但是已經在JDK9中被刪除了,因為官方推薦使用VissualVM。
#基本語法
jhat [options] <heap-dump-file>#基本用法
# 分析堆轉儲文件并在7000端口啟動服務
jhat heap.hprof# 訪問分析結果
http://localhost:7000
參數 | 說明 | 示例 |
---|---|---|
-stack false | 關閉對象分配調用棧跟蹤 | jhat -stack false heap.hprof |
-refs false | 關閉對象引用跟蹤 | jhat -refs false heap.hprof |
-port <port> | 指定HTTP服務器端口(默認7000) | jhat -port 8000 heap.hprof |
-exclude <file> | 指定排除文件(包含排除的類名) | jhat -exclude exclude.txt heap.hprof |
-baseline <file> | 指定基準堆轉儲(用于比較) | jhat -baseline base.hprof heap.hprof |
-debug <int> | 設置調試級別(0-2) | jhat -debug 1 heap.hprof |
-version | 顯示版本信息 | jhat -version |
-h /-help | 顯示幫助信息 | jhat -help |
?這個表示就已經啟動成功了,可以去瀏覽器的http://localhost:8000/進行訪問,這邊建議小伙伴自己去嘗試查看,知道這個東西就可以了,后面我們還是使用GUI圖形界面去分析的,因為這個會更加的直觀的。
jstack:生成 Java 進程的線程快照
我們上篇說到了jamp的堆快照,這里又有個可以查看線程的快照,因為程序出現卡頓不一定是堆堆問題嘛,也可能是線程的問題,jstack獲取線程快照?:顯示所有 Java 線程的調用棧信息,?診斷死鎖?:自動檢測并報告死鎖線程,分析高 CPU 占用?:結合?top
?或?jps
?定位問題線程,排查線程阻塞?:識別等待資源或鎖的線程。
#基本語法
jstack [options] <pid>
參數 | 作用 | 示例 |
---|---|---|
-F | 強制生成線程轉儲(當進程掛起時使用) | jstack -F 1234 |
-l | 顯示額外鎖信息(包含同步器和?java.util.concurrent ?鎖) | jstack -l 1234 |
-m | 混合模式(顯示 Java 和本地方法棧) | jstack -m 1234 |
-h /-help | 顯示幫助信息 | jstack -help |
?這里來說一下區別,和jmap不同的就是他不會要求生成文件然后再分析,而是直接把內容打印到控制臺,當然也是可以存文件的,這個文件就是普通的txt文件不需要其他命令或者工具輔助查看了。
jstack -F 1234 > thread_dump.txt
#其實所有的輸出都可以用這種方式存到指定的文件
#這個就是基本信息了
2025-08-01 17:13:34 //快照時間
Full thread dump Java HotSpot(TM) 64-Bit Server VM (21.0.5+9-LTS-239 mixed mode, emulated-client, sharing): //虛擬機信息Threads class SMR info: //一共30個線程,線程的地址如下
_java_thread_list=0x0000600002111ac0, length=30, elements={
0x0000000127010a00, 0x0000000127011200, 0x0000000127011a00, 0x000000011680f600,
0x000000011680d000, 0x000000011680d800, 0x000000011680aa00, 0x00000001268b2c00,
0x00000001269abc00, 0x0000000117102800, 0x0000000126b09200, 0x0000000127333c00,
0x0000000126b1c000, 0x000000012723ec00, 0x0000000117200e00, 0x0000000126b0e000,
0x0000000117008e00, 0x000000012734f000, 0x000000012734f800, 0x0000000127346200,
0x0000000127346a00, 0x000000011721b800, 0x0000000126b36c00, 0x0000000126b3ec00,
0x0000000126b3f400, 0x0000000126b3fc00, 0x0000000127347200, 0x0000000126b40400,
0x0000000127344600, 0x0000000126820000
}"Reference Handler" #9 [32259] daemon prio=10 os_prio=31 cpu=1.76ms elapsed=141885.62s tid=0x0000000127010a00 nid=32259 waiting on condition [0x000000016ec6e000]
#"Reference Handler"??:線程名稱
??#9?:線程序號(JVM內部編號)
#??[32259]??:原生線程ID(Native Thread ID)
#?daemon?:這是一個守護線程(非用戶線程)
?#prio=10?:Java線程優先級(1-10)
?#os_prio=31?:操作系統線程優先級
?#cpu=1.76ms?:該線程累計使用的CPU時間
?#elapsed=141885.62s?:線程已運行的時間(秒)
?#tid=0x0000000127010a00?:Java線程ID(內存地址)
#?nid=32259?:對應的操作系統線程ID(Native ID)
?#waiting on condition?:線程當前狀態
??#[0x000000016ec6e000]??:線程棧的起始地址java.lang.Thread.State: RUNNABLE//運行狀態at java.lang.ref.Reference.waitForReferencePendingList(java.base@21.0.5/Native Method)at java.lang.ref.Reference.processPendingReferences(java.base@21.0.5/Reference.java:246)at java.lang.ref.Reference$ReferenceHandler.run(java.base@21.0.5/Reference.java:208)
線程狀態(Thread.State)
- ?RUNNABLE?:線程正在執行或準備執行
- ?WAITING?:線程等待某個條件(通常需要喚醒)
- ?BLOCKED?:線程等待獲取鎖
- ?TIMED_WAITING?:線程在指定時間內等待
這個就是jstack的示例,這里說一下什么是?daemon?:守護線程(JVM退出時不等待這些線程)什么是非daemon?:用戶線程(JVM會等待這些線程結束),簡單來說守護線程就是系統后臺線程比如日志監控、垃圾回收等。
jcmd:多功能命令行工具
怎么說呢這哥們就是一個縫合怪,除了不能替代jstat其余的基本上都可以替代了,感覺前面講的是不是有點多余了。
jcmd [options] <pid|main class> <command> [arguments]
部分 | 含義 | 是否必須 | 示例 |
---|---|---|---|
jcmd | 命令本身 | 必須 | jcmd |
[options] | 全局選項 | 可選 | -l ,?-f |
<pid|main class> | 目標進程標識 | 必須 | 1234 ?或?com.example.MyApp |
<command> | 要執行的診斷命令 | 可選 | Thread.print ,?GC.heap_dump |
[arguments] | 命令參數 | 可選 | filename=/tmp/dump.hprof |
命令 | 作用 | 示例 |
---|---|---|
VM.flags | 查看JVM參數 | jcmd 1234 VM.flags |
VM.system_properties | 查看系統屬性 | jcmd 1234 VM.system_properties |
VM.uptime | 顯示JVM運行時間 | jcmd 1234 VM.uptime |
VM.version | 顯示JVM版本 | jcmd 1234 VM.version |
Thread.print | 生成線程轉儲 | jcmd 1234 Thread.print |
GC.class_histogram | 顯示類直方圖 | jcmd 1234 GC.class_histogram |
GC.heap_dump | 生成堆轉儲文件 | jcmd 1234 GC.heap_dump /path/to/dump.hprof |
GC.run_finalization | 強制執行finalize | jcmd 1234 GC.run_finalization |
GC.run | 顯式觸發GC | jcmd 1234 GC.run |
JFR.start | 開始JFR記錄 | jcmd 1234 JFR.start name=myrec settings=profile |
JFR.dump | 導出JFR記錄 | jcmd 1234 JFR.dump name=myrec filename=rec.jfr |
JFR.stop | 停止JFR記錄 | jcmd 1234 JFR.stop name=myrec |
VM.native_memory | 本地內存統計 | jcmd 1234 VM.native_memory summary |
?突然感覺這個命令有點復雜了有木有,主包這邊就不演示了,這么多參數和命令又點頭疼,具體使用什么命令還是要看小伙伴自己和使用的場景,有興趣的小伙伴自己去試試看吧。
jstatd:遠程監控工具
作用就是為遠程主機提供 JVM 監控數據,通過 RMI 協議提供監控數據,可同時監控多個 Java 進程,支持 VisualVM、JConsole 等工具連接,這個咱們就簡單說一下就好了,因為大多數生成環境是不允許的,多開一個端口都是有風險的。
#基本語法
jstatd [options]
#實例
jstatd -J-Djava.security.policy=jstatd.policy -p 3333
參數 | 作用 | 示例 |
---|---|---|
-p <port> | 指定 RMI 注冊端口 | jstatd -p 1099 |
-n <name> | 指定 RMI 注冊名稱 | jstatd -n MyJstatd |
-J<option> | 傳遞參數給 JVM | jstatd -J-Djava.security.policy=my.policy |
-nr | 不創建 RMI 注冊表 | jstatd -nr |
-r <port> | 指定 RMI 注冊表端口 | jstatd -r 1099 |
-h /-help | 顯示幫助信息 | jstatd -h |
?總結
本篇把剩下的命令行已經全部介紹完了,下一篇講講GUI圖形界面,大家好好練習命令吧。