要分析Tomcat的線程狀態,首先需要獲取其進程ID。在Ubuntu終端中執行以下命令:
pgrep -f tomcat
或通過ps
命令過濾:
ps -ef | grep tomcat | grep -v grep | awk '{print $2}'
輸出的數字即為Tomcat的主進程ID(如12345
)。
線程轉儲是診斷死鎖的核心工具,它記錄了所有線程的狀態、堆棧軌跡及鎖持有情況。在Ubuntu中,可通過以下兩種方式生成:
jstack
命令(需JDK環境)jstack -l <Tomcat_PID> > /var/log/tomcat/thread_dump_$(date +%F_%T).log
其中-l
參數會額外打印鎖的附加信息(如java.lang.Thread.State: BLOCKED
的鎖定對象),有助于定位死鎖根源。SIGQUIT
信號(無需額外工具)kill -3 <Tomcat_PID>
該命令會將線程轉儲輸出到Tomcat的默認日志文件catalina.out
中(路徑通常為/var/log/tomcat/catalina.out
)。生成線程轉儲后,需通過關鍵詞快速定位死鎖信息:
grep
命令在轉儲文件中查找“deadlock”(不區分大小寫),若存在死鎖,日志會明確提示:grep -i "deadlock" /var/log/tomcat/thread_dump_$(date +%F_%T).log
示例輸出:Found one Java-level deadlock:
=============================
"Thread-1":
waiting to lock monitor 0x00007f8a1c003ae8 (object 0x000000076b5b6b98, a java.lang.Object),
which is held by "Thread-2"
"Thread-2":
waiting to lock monitor 0x00007f8a1c004b28 (object 0x000000076b5b6ba8, a java.lang.Object),
which is held by "Thread-1"
上述輸出清晰展示了死鎖線程(Thread-1
和Thread-2
)及它們互相等待的鎖對象。BLOCKED
(阻塞)狀態,且堆棧中包含waiting to lock
或- locked
字樣。例如:"Thread-1" #11 prio=5 os_prio=0 tid=0x00007f8a1c001000 nid=0x1e34 waiting for monitor entry [0x00007f8a0a7fe000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.DeadlockExample.methodA(DeadlockExample.java:20)
- waiting to lock <0x000000076b5b6b98> (a java.lang.Object)
at com.example.DeadlockExample.run(DeadlockExample.java:15)
結合多個線程的BLOCKED
狀態及鎖依賴關系(如Thread-1
等待Thread-2
持有的鎖,Thread-2
又等待Thread-1
持有的鎖),可推斷出死鎖。locked
或waiting to lock
后面的對象地址(如0x000000076b5b6b98
),相同地址的對象是線程爭奪的核心。com.example.DeadlockExample.methodA
),便于后續修復。Thread-1
先鎖ObjectA
再鎖ObjectB
,Thread-2
先鎖ObjectB
再鎖ObjectA
),易引發死鎖,需調整鎖獲取順序。通過以上步驟,可在Ubuntu系統的Tomcat日志中有效查找并定位線程死鎖問題。若需更直觀的分析,可將線程轉儲導入在線工具(如fastthread.io),自動解析死鎖及線程狀態。