當 Java 應用出現 CPU 飆高、死鎖、響應緩慢等問題時,jstack 是最直接、無侵入的現場診斷工具。本文提供一個生產環境可用的 Shell 腳本,實現定時、批量導出指定 Java 進程的線程快照,便於事後離線分析。
#!/bin/bash
# 配置區 ---------------------------------------------------
PROCESS_NAME="java" # 進程關鍵字
JSTACK_PATH="/usr/java/jdk1.8.0_202/bin/jstack" # jstack 絕對路徑
LOG_DIR="/var/log/jstack_dumps" # 輸出目錄
# ---------------------------------------------------------
mkdir -p "$LOG_DIR"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# 獲取目標進程 PID 列表(排除 grep 自身)
PIDS=$(pgrep -f "$PROCESS_NAME" | grep -v $$)
if [ -z "$PIDS" ]; then
echo "[$(date)] 未找到匹配進程: $PROCESS_NAME"
exit 0
fi
for PID in $PIDS; do
OUTFILE="${LOG_DIR}/jstack_${PID}_${TIMESTAMP}.log"
echo "[$(date)] 正在導出 PID=$PID 到 $OUTFILE"
# -l 參數:長列表模式,包含鎖信息;-F 強制模式(進程掛起時使用)
"$JSTACK_PATH" -l "$PID" > "$OUTFILE" 2>&1
if [ $? -eq 0 ]; then
echo "[$(date)] 導出成功,大小: $(du -h "$OUTFILE" | cut -f1)"
else
echo "[$(date)] 導出失敗,請檢查權限或進程狀態"
fi
done
| 參數 | 作用 | 建議 |
|---|---|---|
-l | 長列表模式,輸出 java.util.concurrent 鎖的額外信息 | 生產排查必加 |
-F | 強制執行(進程無響應時) | 慎用,可能導致 JVM 暫停更久 |
-m | 混合模式,同時輸出 Native C/C++ 堆棧 | 需排查 JNI/底層崩潰時使用 |
# crontab -e
# 每 5 分鐘自動導出一次,保留最近 7 天
*/5 * * * * /opt/scripts/auto_jstack.sh >> /var/log/jstack_cron.log 2>&1
# 定期清理舊文件
0 3 * * * find /var/log/jstack_dumps -type f -mtime +7 -delete
| 狀態 | 關鍵字 | 典型成因 |
|---|---|---|
| RUNNABLE | running / in native | 正常執行 / JNI 呼叫 / GC 線程 |
| BLOCKED | waiting for monitor entry | 同步鎖競爭、死鎖候選 |
| WAITING | waiting on <address> | Object.wait()、Thread.join() |
| TIMED_WAITING | sleeping / waiting with timeout | Thread.sleep()、wait(timeout) |
BLOCKED 且互相持有對方所需鎖的線程對WAITING 於同一條件隊列將 jstack 自動化導出納入常規運維體系,配合關鍵狀態識別與可視化工具,能將 Java 疑難雜癥的平均定位時間(MTTR)從小時級壓縮至分鐘級。建議在專案啟動腳本中集成此腳本,實現「開箱即用」的觀測能力。