jstack 是 JDK 自帶的線程堆棧快照工具,輸出 JVM 當前所有線程的調用棧,是生產環境故障排查的「核磁共振」。
| 參數 | 作用 | |
|---|---|---|
-l | 長列表模式:顯示鎖信息(自有鎖、等待鎖),排查死鎖必加 | |
-m | 混合模式:同時輸出 Java 棧與 Native C/C++ 棧(需調試符號) | |
-F | 強制輸出:進程掛起無響應時使用(慎用,可能凍結 JVM) |
| 狀態 | 含義 | 關注點 |
|---|---|---|
| RUNNABLE | 運行中/就緒 | 長期 RUNNABLE 且佔用高 CPU → 熱點代碼/死循環 |
| BLOCKED | 等待監視器鎖 | 大量 BLOCKED → 鎖競爭/死鎖 |
| WAITING | 無限期等待 | Object.wait()、Thread.join()、LockSupport.park() |
| TIMED_WAITING | 限時等待 | sleep、wait(timeout)、join(timeout)、parkNanos |
| TERMINATED | 已結束 | 正常結束或異常退出 |
搜索關鍵字:Found one Java-level deadlock 或手動分析:
"Thread-1" waiting for <0x000000076c1b2c38> (a java.lang.Object)
at DeadlockDemo$1.run(DeadlockDemo.java:21)
- waiting to lock <0x000000076c1b2c38>
- locked <0x000000076c1b2c48>
"Thread-2" waiting for <0x000000076c1b2c48> (a java.lang.Object)
at DeadlockDemo$2.run(DeadlockDemo.java:31)
- waiting to lock <0x000000076c1b2c48>
- locked <0x000000076c1b2c38>
判斷:Thread-1 持有鎖 A 等鎖 B,Thread-2 持有鎖 B 等鎖 A → 死鎖。
top -H -p 找出佔用 CPU 最高的線程 ID (LWP),如 12345printf '%x\n' 12345 → 0x3039nid=0x3039,定位該線程棧BLOCKED 線程:被誰阻塞?鎖在哪行代碼?WAITING/TIMED_WAITING:等待什麼資源?DB 連接池?HTTP 調用?鎖?java.net.SocketInputStream.socketRead0 → 網絡 I/O 等待對比不同時刻的 dump,線程數持續增長且名稱相似(如 Thread-12345、pool-5-thread-1),檢查:
thread -b 自動檢測阻塞鏈new Thread(task, "Order-Process-Worker"),dump 中一眼識別業務。-l 參數輸出的 locked <0x...> 是定位鎖競爭關鍵。