[翻譯]Java排錯指南 - 5 確定崩潰何地發生
本文來自 fairjm@圖靈社群 轉截請註明出處
這幾天公司其他組遇到了一個segmentation fault的問題,找到了這個官方文件,基於Java8,感覺不錯就翻譯了下. 一些地方翻譯比較生硬,如有問題請麻煩指正~^_^
原文地址: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/crashes001.html
這幾天公司其他組遇到了一個segmentation fault的問題,找到了這個官方文件,基於Java8,感覺不錯就翻譯了下.
一些地方翻譯比較生硬,如有問題請麻煩指正~^_^ by fairjm
5.1 確定崩潰發生在哪裡
這一節提供了一些例子來演示如何使用錯誤日誌來找到崩潰的原因,並且給出一些排查這些問題的建議.
錯誤日誌的頭指出了錯誤的型別和有問題的幀(frame),thread stack指出了當前的執行緒和堆疊軌跡.檢視Header Format
Crash in Native Code
Crash in Compiled Code
Crash in HotSpot Compiler Thread
Crash in VM Thread
Crash Due to Stack Overflow
5.1.1 原生程式碼崩潰
如果致命錯誤日誌(fatal error log)指出的問題幀來自於本地庫,那麼可能是本地庫或者JNI庫程式碼存在bug.這種崩潰當然也有可能是其他原因造成的,但是分析這個庫和其他的core file或者crash dump是一個很好的開始.
以下是一個致命錯誤日誌的頭:
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# SIGSEGV (0xb) at pc=0x417789d7, pid=21139, tid=1024
#
# Java VM: Java HotSpot(TM) Server VM (6-beta2-b63 mixed mode)
# Problematic frame:
# C [libApplication.so+0x9d7]
在這個例子中,SIGSEGV
發生線上程執行libApplication.so
中的程式碼.
一些其他例子是Java VM的本地庫導致的.在下面的例子中,JavaThread
在_thread_in_vm
狀態中失敗了(表明它正在執行Java VM程式碼)
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x08083d77, pid=3700, tid=2896
#
# Java VM: Java HotSpot(TM) Client VM (1.5-internal mixed mode)
# Problematic frame:
# V [jvm.dll+0x83d77]
--------------- T H R E A D ---------------
Current thread (0x00036960): JavaThread "main" [_thread_in_vm, id=2896]
:
Stack: [0x00040000,0x00080000), sp=0x0007f9f8, free space=254k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [jvm.dll+0x83d77]
C [App.dll+0x1047] <========= C/native frame
j Test.foo()V+0
j Test.main([Ljava/lang/String;)V+0
v ~StubRoutines::call_stub
V [jvm.dll+0x80f13]
V [jvm.dll+0xd3842]
V [jvm.dll+0x80de4]
V [jvm.dll+0x87cd2]
C [java.exe+0x14c0]
C [java.exe+0x64cd]
C [kernel32.dll+0x214c7]
:
在這個例子中,雖然出問題的幀是VM的,執行緒棧顯示一個本地例子(native routine)App.dll
已經被VM呼叫(可能是通過JNI).
解決這個本地庫崩潰的第一步是調查本地庫發生崩潰的那段原始碼.
- 如果本地庫是由你的應用程式提供,那麼調查本地庫的原始碼.大量的問題可以通過在執行應用程式時使用-Xcheck:jni
引數被識別.檢視The -Xcheck:jni Option.
- 如果這個本地庫是由其他供應商提供,被你的程式所使用,那麼就向他們提供bug報告和致命錯誤日誌資訊.
- 如果本地庫是來自於JRE的(比如awt.dll,net.dll或其他的),那有可能你遇到了一個庫或者API的bug.那麼就儘可能獲取足夠的資訊提交一個bug並指名庫名稱.你可以在JRE的發行版中的 jre/lib 或 jre/bin目錄中找到JRE的庫.
如果可能的話,你可以通過本地debugger attach到core file或crash dump的方式來排查本地庫崩潰.取決於你所使用的系統,本地debugger有dbx
,gdb
,或windbg
.檢視 Native Operating System Tools
5.1.2 編譯程式碼崩潰
如果致命錯誤日誌指出崩潰發生在編譯程式碼(compiled code),那有可能你遇到了一個編譯器導致的不正確程式碼生成的bug.你可以通過問題堆疊的型別是J
(代表一個compiled java frame)來識別.
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# SIGSEGV (0xb) at pc=0x0000002a99eb0c10, pid=6106, tid=278546
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (1.6.0-beta-b51 mixed mode)
# Problematic frame:
# J org.foobar.Scanner.body()V
#
:
Stack: [0x0000002aea560000,0x0000002aea660000), sp=0x0000002aea65ddf0,
free space=1015k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
J org.foobar.Scanner.body()V
[error occurred during error reporting, step 120, id 0xb]
注意:該例子無法獲得一個完整的執行緒棧.輸出的"error occurred during error reporting" 表示問題發生在試圖獲取堆疊跟蹤(可能是棧損壞了).
通過更換編譯器的方式可能可以臨時解決(例如使用HotSpot Client VM取代HotSpot Server VM,或反過來)或者從編譯中排除掉導致崩潰的方法.在這個例子中,將64位的Server VM換成32位的Client VM可能會有用.
更多可能的規避措施見Working Around Crashes in the HotSpot Compiler Thread or Compiled Code.
5.1.3 HotSpot編譯器執行緒崩潰
如果核心錯誤日誌顯示的當前執行緒是一個叫CompilerThread0
,CompilerThread1
或AdapterCompiler
的JavaThread
,那麼你可能遇上了編譯器bug.可能解決方式和上一節一樣.(懶得復讀了...)
5.1.4 VM執行緒崩潰
如果核心錯誤日誌顯示的當前執行緒是VMThread
,那麼檢視一下在THREAD
那節包含VM_Operation
的那一行.VMThread
是特殊的的HotSpot VM執行緒.它執行一些特殊的工作比如GC.如果VM_Operation
表明操作是GC,那麼你可能遇到了諸如堆損壞的問題.
包括GC問題之外,它同樣可能是一些其他問題(例如編譯器或者執行時bug)導致的物件引用在堆中處於一個不完整和不正確的狀態.這種情況下,收集儘可能多的環境資訊和嘗試可能的規避方案.如果發現和GC有關,你可能通過修改GC配置的方式來臨時保證正常執行.
對於更多的規避方案,檢視Working Around Crashes during Garbage Collection
5.1.5 爆棧崩潰
java語言的一個棧溢位通常會導致執行緒丟擲煩人的java.lang.StackOverflowError
異常.另一方面,C和C++寫入超過了棧的結束會引起一個棧溢位.這是一個致命的錯誤,會導致程式終止.
在HotSpot實現中,Java方法和C/C++原生程式碼共享棧幀,即使用者原生程式碼和VM自身.
Java方法產生的程式碼會檢查棧離棧的結束是否會有固定距離可用的空間,所以原生程式碼的呼叫可以不擔心是否會超過棧空間.
到棧結束的距離被稱為Shadow Pages
.這個大小取決於所在平臺,shadow pages在3到20頁之間.
這個距離是可以調整的,所以應用使用到了原生程式碼想要比預設更大的距離時可以增加shadow page的大小.
增加的引數是-XX:StackShadowPages=n
,n設定為比當前平臺預設值大.
如果你的應用遇上了segmentation fault但是沒有core file或致命錯誤日誌參見Appendix A,或者在windows上STACK_OVERFLOW_ERROR
,或者得到一個訊息"An irrecoverable stack overflow has occurred",這說明超過了StackShadowPages
,需要更大的空間.
如果你增加了StackShadowPages
,你可能也需要使用-Xss
引數增加預設的執行緒棧大小.增加預設的執行緒棧大小可能會減少可建立的執行緒數,所以請小心選擇這個數值.執行緒棧的大小於不同平臺上在256KB到1024KB.
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x10001011, pid=296, tid=2940
#
# Java VM: Java HotSpot(TM) Client VM (1.6-internal mixed mode, sharing)
# Problematic frame:
# C [App.dll+0x1011]
#
--------------- T H R E A D ---------------
Current thread (0x000367c0): JavaThread "main" [_thread_in_native, id=2940]
:
Stack: [0x00040000,0x00080000), sp=0x00041000, free space=4k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [App.dll+0x1011]
C [App.dll+0x1020]
C [App.dll+0x1020]
:
C [App.dll+0x1020]
C [App.dll+0x1020]
...<more frames>...
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j Test.foo()V+0
j Test.main([Ljava/lang/String;)V+0
v ~StubRoutines::call_stub
你可以從例子中獲得以下資訊:
- 異常是EXCEPTION_STACK_OVERFLOW
- 執行緒的狀態是_thread_in_native
,表示執行緒在執行native或者JNI程式碼.
- 執行緒資訊中,可用的空間僅僅只有4KB(windows系統中的單頁).另外執行緒指標(sp)在0x00041000
,很接近棧結束0x00040000
.
- 輸出的本地棧顯示一個遞迴的本地方法是這個問題的原因....<more frames>...
表明還有更多的幀存在但是沒有輸出.輸出只限於100幀.
相關資料:
Do we need Unsafe in Java?
Shortest code that raises a SIGSEGV
Best way on how to solve/debug JVM crash (SIGSEGV)
JVM crash. Problematic frame: J 4518 C2 java.lang.Long.getChar
相關文章
- SAP Spartacus internationalization ( i18n ) 翻譯問題的排錯指南
- Qt程式繼承QApplication發生崩潰的原因QT繼承APP
- WkWebView 令人崩潰的崩潰WebView
- 【除錯技巧】Dialog dismiss 崩潰除錯
- Flutter: BottomNavigationBar + PageView 翻頁時崩潰FlutterNavigationView
- 突發:當機崩潰OOMOOM
- WKWebView崩潰WebView
- Redis崩潰Redis
- TestBird 崩潰分析(Artisan) Android SDK 使用指南Android
- iOS開發的底線-崩潰iOS
- 如何使Java虛擬機器崩潰Java虛擬機
- 5 Java NIO Scatter 與Gather-翻譯Java
- Facebook是如何防止訊息系統在新年前夕發生崩潰?
- Crittercism:KitKat崩潰率0.7% iOS 7.1崩潰率1.6%iOS
- [翻譯-Shiro]-Apache Shiro Java認證指南ApacheJava
- [翻譯-Shiro]-Apache Shiro Java 授權指南ApacheJava
- APP防崩潰APP
- QT TS檔案翻譯,部分不能正確被翻譯QT
- [翻譯]現代java開發指南 第一部分Java
- WWDC 2018:理解崩潰以及崩潰日誌
- vs2010除錯崩潰 reflector除錯
- 一個不相容的 JS 方法,讓你的網站發生崩潰JS網站
- Angular 5 開發一個有道翻譯Angular
- 應用崩潰了?Android vitals 幫您精確診斷應用崩潰Android
- 生產級部署 Python 指令碼,崩潰可自啟!Python指令碼
- iOS Crash不崩潰iOS
- linux mint 崩潰Linux
- ios 崩潰集錦iOS
- app 崩潰的原因APP
- 【Azure Cloud Services】雲服務頻繁發生伺服器崩潰的排查方案Cloud伺服器
- COM+物件池元件崩潰除錯手記 (轉)物件元件除錯
- 執行緒崩潰為什麼不會導致 JVM 崩潰執行緒JVM
- 不要升級!不要升級!MacOS 14.4 引發Java 應用崩潰MacJava應用崩潰
- 微信翻譯大型翻車現場?機器翻譯到底有哪些不確定性
- 記一次VMware的崩潰除錯分析過程除錯
- Node出錯導致執行崩潰的解決方案
- IOS 崩潰日誌分析iOS
- Invalid double崩潰分析