首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JVM 致命錯誤日誌 hs_err_pid.log 深度解讀指南

     編輯:Java 相關知識

前言

當 JVM 發生嚴重錯誤(如 Segmentation Fault)導致進程崩潰時,會自動生成一份命名為 hs_err_pid<pid>.log 的錯誤日誌檔案。這份日誌包含了診斷崩潰根因的關鍵資訊,是排查 JVM Crash、Native Memory 問題、JNI 錯誤的核心依據。本文將以一份實際的 Linux 環境下 Eclipse 崩潰日誌為例,逐段深度解析各區塊含義與排查思路。

日誌檔案基本資訊

  • 預設位置:工作目錄(權限不足時會嘗試寫入 /tmp)
  • 自訂路徑:啟動參數 -XX:ErrorFile=/var/log/java/Java_error%p.log(%p 代表 PID)
  • 包含內容:觸發信號、版本配置、崩潰線程詳情、所有線程狀態、堆記憶體摘要、載入的 Native 庫、JVM 參數、環境變數、OS/CPU 資訊

逐段詳細解析

1. 標題區:錯誤概要

# SIGSEGV (0xb) at pc=0x03568cf4, pid=16819, tid=3073346448
欄位含義
SIGSEGV信號名稱:Segmentation Fault(記憶體存取違規)
0xb信號編號(Linux x86 上 SIGSEGV = 11 = 0xb)
pc=0x03568cf4程式計數器值,崩潰時正在執行的指令位址
pid=16819進程 ID
tid=3073346448線程 ID(Linux 下為 pthread_t 數值)

關鍵判斷:SIGSEGV 通常意味著 Native 代碼(JNI、Native 庫、JVM 本身)嘗試存取無效記憶體位址。

2. 版本資訊區

# JRE version: 6.0_32-b05
# Java VM: Java HotSpot(TM) Server VM (20.7-b02 mixed mode Linux-x86 )

確認 JDK 版本、VM 模式(Server/Client)、混合模式(Mixed Mode:解釋執行 + JIT 編譯)、作業系統架構。排查時請優先對照已知 Bug 數據庫(如 Oracle Bug Database)。

3. 問題幀

# Problematic frame:
# C  [libgtk-x11-2.0.so.0+0x19fcf4]  __float128+0x19fcf4
幀類型說明
CNative C/C++ 幀(最常見於 JNI、Native 庫、JVM 運行時)
j解釋執行的 Java 幀
VVM 內部幀
JJIT 編譯後的 Java 幀
vVM 生成的存根幀

關鍵線索:此處 C 幀指向 libgtk-x11-2.0.so.0(GTK 圖形庫),偏移量 0x19fcf4。結合 pc 值,可定位至具體 Native 函數。此例顯示 Eclipse SWT 呼叫 GTK 導致崩潰。

4. 當前線程詳情

Current thread (0x09f30c00):  JavaThread "main" [_thread_in_native, id=16822, stack(0xb72a8000,0xb72f9000)]
  • 0x09f30c00:JVM 內部線程物件指標
  • JavaThread:線程類型(其他:VMThread、CompilerThread、GCTaskThread 等)
  • main:線程名稱
  • _thread_in_native:關鍵狀態,表示崩潰發生在 Native 代碼執行期間,強烈暗示 Native 代碼或 JNI 問題
  • stack(0xb72a8000,0xb72f9000):線程棧記憶體範圍

5. 信號與暫存器資訊

siginfo: si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x00000010
EAX=0x00000000, EBX=0x0375dd84, ECX=0x00000000, EDX=0x00000000
ESP=0xb72f0fa0, EBP=0xb72f0fb8, ESI=0x00000000, EDI=0x0a6c1800
EIP=0x03568cf4, EFLAGS=0x00010246, CR2=0x00000010
  • si_code=1 (SEGV_MAPERR):存取的位址未映射(非權限錯誤)
  • si_addr=0x10:嘗試存取的無效位址(極小值通常暗示 NULL 指標解引用且帶偏移)
  • EIP=pc:指令指標寄存器,指向崩潰指令
  • ESP/EBP:棧指標/基址指標,用於棧回溯

6. 棧頂指令碼

Instructions: (pc=0x03568cf4)
0x03568cd4:  89 14 24 89 75 f8 89 d6 89 7d fc 89 c7 e8 7e 1b
0x03568ce4:  ea ff 89 34 24 89 87 d4 02 00 00 e8 30 00 ea ff
0x03568cf4:  8b 40 10 89 3c 24 c7 44 24 08 00 00 00 00 89 87
0x03568d04:  d0 02 00 00 8b 83 88 24 00 00 89 44 24 04 e8 dd

崩潰位址附近的機器碼,可用反組譯工具(如 objdump、gdb)轉為組合語言,進一步分析具體指令行為。

7. 暫存器到記憶體映射

Register to memory mapping:
EAX=0x00000000 is an unknown value
EBX=0x0375dd84:  in /usr/lib/libgtk-x11-2.0.so.0 at 0x033c9000
ESP=0xb72f0fa0 is pointing into the stack for thread: 0x09f30c00
EBP=0xb72f0fb8 is pointing into the stack for thread: 0x09f30c00

關鍵發現:EBX 指向 libgtk-x11-2.0.so.0 內部位址,佐證崩潰發生在 GTK 庫內部。

8. 線程棧回溯

Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libgtk-x11-2.0.so.0+0x19fcf4]  __float128+0x19fcf4
C  [libgtk-x11-2.0.so.0+0x1a32c0]  __float128+0xc0
...
C  [libswt-pi-gtk-3738.so+0x33f6a]  Java_org_eclipse_swt_internal_gtk_OS__1Call+0xf
J  org.eclipse.swt.internal.gtk.OS._Call(III)I
J  org.eclipse.swt.internal.gtk.OS.Call(III)I

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J  org.eclipse.swt.internal.gtk.OS._Call(III)I
J  org.eclipse.swt.internal.gtk.OS.Call(III)I
j  org.eclipse.swt.widgets.Widget.fixedSizeAllocateProc(II)I+5
j  org.eclipse.swt.widgets.Display.fixedSizeAllocateProc(II)I+17
  • Native Frames:從底層 C 庫向上追蹤到 JNI 橋接函數 Java_org_eclipse_swt_internal_gtk_OS__1Call
  • Java Frames:從 JNI 進入點向上追蹤到 SWT Widget 配置邏輯
  • 結論:Eclipse SWT 透過 JNI 呼叫 GTK 原生庫進行 UI 佈局時觸發崩潰

9. 所有 Java 線程列表

Java Threads: ( => current thread )
  0x0b4c1000 JavaThread "Worker-247" [_thread_blocked, id=25417, stack(0x741bc000,0x7420d000)]
  0x0a300c00 JavaThread "Worker-246" [_thread_blocked, id=25235, stack(0x7d30c000,0x7d35d000)]
  ...

列出所有 Java 線程狀態(_thread_blocked、_thread_in_native 等),可檢查是否有死鎖、大量阻塞線程等異常模式。

10. VM 狀態與鎖資訊

VM state: not at safepoint (normal execution)
VM Mutex/Monitor currently owned by a thread: None
  • not at safepoint:崩潰發生於正常執行期,非 GC 或停頓階段
  • Mutex/Monitor:JVM 內部鎖狀態,若有死鎖會顯示持有者

11. 堆記憶體詳情

Heap
 PSYoungGen      total 149056K, used 125317K [0xa9700000, 0xb41a0000, 0xb41a0000)
  eden space 123520K, 95% used [0xa9700000,0xb0ac0de0,0xb0fa0000)
  from space 25536K, 26% used [0xb28b0000,0xb2f50748,0xb41a0000)
  to   space 25600K, 0% used [0xb0fa0000,0xb0fa0000,0xb28a0000)
 PSOldGen        total 261248K, used 239964K [0x941a0000, 0xa40c0000, 0xa9700000)
  object space 261248K, 91% used [0x941a0000,0xa2bf7018,0xa40c0000)
 PSPermGen       total 163328K, used 130819K [0x841a0000, 0x8e120000, 0x941a0000)
  object space 163328K, 80% used [0x841a0000,0x8c160c40,0x8e120000)
  • 使用 Parallel Scavenge GC(PSYoungGen、PSOldGen)
  • 老年代使用率 91%,接近滿載,可能觸發頻繁 Full GC
  • 永久代 80%,類載入量較大(Eclipse 插件多)

12. Code Cache

Code Cache [0xb4262000, 0xb5ac2000, 0xb7262000)
 total_blobs=5795 nmethods=5534 adapters=209 free_code_cache=25103616 largest_free_block=38336

JIT 編譯代碼緩存區,與永久代分離。關注 free_code_cache 與 largest_free_block,過小會導致 JIT 停止編譯,影響效能。

13. 動態載入庫

Dynamic libraries:
00101000-00122000 r-xp 00000000 08:01 3483560  /usr/lib/libjpeg.so.62.0.0
00122000-00123000 rwxp 00020000 08:01 3483560  /usr/lib/libjpeg.so.62.0.0
...

進程虛擬記憶體映射表。每行格式:起始-結束 權限 偏移 主設備號:次設備號 inode 路徑。用途:確認崩潰時載入哪些 Native 庫、版本是否正確、是否有衝突庫、堆/棧/守護頁位置。

14. JVM 參數與環境變數

VM Arguments:
jvm_args: -DOSgi.requiredJavaVersion=1.5 -XX:MaxPermSize=256m -Xms40m -Xmx512m ...
Java_command: /.../eclipse/plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar ...
Environment Variables:
PATH=...
DISPLAY=:0.0

關鍵排查點:-Xmx/-Xms 堆大小、-XX:MaxPermSize 永久代大小、DISPLAY 圖形環境(SWT/GTK 依賴)。

15. 訊號處理器與 OS/硬體資訊

Signal Handlers:
SIGSEGV: [libjvm.so+0x726440], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004
...
OS: Red Hat Enterprise Linux Client release 5.4 (Tikanga)
CPU: total 4 (4 cores per cpu, 1 threads per core) family 6 model 42 stepping 7
Memory: 4k page, physical 3631860k(155144k free), swap 5124724k(5056452k free)
  • JVM 註冊的訊號處理器位址(在 libjvm.so 內)
  • OS 版本、Kernel 版本、glibc 版本
  • CPU 拓撲、指令集支援
  • 實體記憶體與 Swap 使用情況(此例實體記憶體剩餘僅 155MB,記憶體壓力大)

綜合排查建議

  1. 優先看 Problematic Frame:定位是 JVM Bug、JNI 代碼、第三方 Native 庫還是應用層邏輯
  2. 對照已知 Bug:搜尋 JDK 版本 + 庫名稱 + 錯誤特徵,如 JDK 6u32 libgtk crash
  3. 升級策略:優先升級 JDK 至更新版本(含 HotSpot 修復)、升級 Native 庫(GTK、SWT)
  4. 記憶體壓力檢查:此例實體記憶體極低,建議增加實體記憶體或減少 -Xmx/MaxPermSize
  5. 啟用核心轉儲:ulimit -c unlimited 並配合 gdb 分析 core 檔案可獲取更完整調用棧

總結

hs_err_pid.log 是 JVM 崩潰現場的「黑盒錄音器」。掌握其結構與關鍵欄位解讀方法,能將模糊的「程式掛了」轉化為具體的「GTK 庫在 SWT 呼叫下觸發空指標解引用」,進而制定精準修復方案。建議將日誌分析納入生產環境故障應急 SOP 中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved