2011-10-28 55 views
7

我正在調查偶爾在我的應用程序中發生的JVM崩潰。 hs_err文件包含關於崩潰的以下詳細信息。JVM崩潰日誌中的BufferBlob :: Interpreter是什麼意思?

# SIGSEGV (0xb) at pc=0x065e68f4, pid=20208, tid=570166160 
# 
# Java VM: Java HotSpot(TM) Server VM (10.0-b23 mixed mode linux-x86) 

...

# Problematic frame: 
# V [libjvm.so+0x5e68f4] 

...

Current thread (0x099ea800): JavaThread "Thread-315" daemon [_thread_in_vm, id=25782, stack(0x21fa3000,0x21fc1000)] 

...

vm_info: Java HotSpot(TM) Server VM (10.0-b23) for linux-x86 JRE (1.6.0_07-b06), built on Jun 10 2008 01:20:15 by "java_re" with gcc 3.2.1-7a (J2SE release) 

所以這告訴我,JVM運行時的一些打段錯誤Java代碼。錯誤日誌還包含有關崩潰線程的堆棧的信息。

Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) 
V [libjvm.so+0x5e68f4] 
V [libjvm.so+0x1c054f] 
V [libjvm.so+0x1bfef2] 
V [libjvm.so+0x1bf57f] 
V [libjvm.so+0x592495] 
V [libjvm.so+0x365c4e] 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
v ~BufferBlob::Interpreter 
J org.myapp.AppClass.getBytes()Lorg/myapp/ByteHolder; 

我已經使用GDB從崩潰連接到核心文件,並獲得有關堆棧的更多細節。這給了我以下輸出。

#5 <signal handler called> 
#6 0x065e68f4 in interpretedVFrame::monitors() const() 
    from /usr/java/jdk1.6.0_07/jre/lib/i386/server/libjvm.so 
#7 0x061c054f in get_or_compute_monitor_info(JavaThread*)() 
    from /usr/java/jdk1.6.0_07/jre/lib/i386/server/libjvm.so 
#8 0x061bfef2 in revoke_bias(oopDesc*, bool, bool, JavaThread*)() 
    from /usr/java/jdk1.6.0_07/jre/lib/i386/server/libjvm.so 
#9 0x061bf57f in BiasedLocking::revoke_and_rebias(Handle, bool, Thread*)() 
    from /usr/java/jdk1.6.0_07/jre/lib/i386/server/libjvm.so 
#10 0x06592495 in ObjectSynchronizer::fast_enter(Handle, BasicLock*, bool, Thread*)() 
    from /usr/java/jdk1.6.0_07/jre/lib/i386/server/libjvm.so 
#11 0x06365c4e in InterpreterRuntime::monitorenter(JavaThread*, BasicObjectLock*)() 
    from /usr/java/jdk1.6.0_07/jre/lib/i386/server/libjvm.so 

這表明原始錯誤報告中列出的六個libjvm.so幀與抓取Java鎖有關。但是,我在org.myapp.AppClass.getBytes()中找不到任何使用任何鎖的代碼。

堆棧中的BufferBlob :: Interpreter行是什麼意思?這些Java堆棧框架? JVM堆棧幀?是否有可能計算出這些堆棧幀中被調用的內容?

注意:請不要建議我嘗試切換到較新的Hotspot JVM。我依賴於CMS收集器,並且最近的所有V1.6 Hotspot JVM都不會對CMS收集器足夠穩定。

編輯:本文檔(http://www.oracle.com/technetwork/java/javase/tsg-vm-149989.pdf)指出「v」幀是「VM生成的末端框架」。任何想法這意味着什麼?

EDIT2:org.myapp.AppClass.getBytes()從DataInputStream中讀取數據。這可能涉及以下堆棧跟蹤:

AppClass.getBytes() 
AppClass.readByte() 
DataInputStream.readByte() 
SocketInputStream.read() 
SocketInputStream.read(byte[],int,int) 
PlainSocketImpl.aquireFD() 

此最終方法獲取鎖。這可能是最終調用上面列出的JVM代碼的來源。上面的堆棧具有整潔的特性,getBytes()下面有5個Java堆棧幀。這將與「Java框架」列表中的5行BufferBlob :: Interpreter整齊地匹配。

這就提出了一些新的問題:

  • 是否有可能在「本機框架」 部分是相同線路的「Java的框架下,只是重複的5條線路BufferBlob ::口譯「 部分?
  • 錯誤日誌爲什麼不顯示這5個堆棧幀的詳細信息?

EDIT3 - 此甲骨文錯誤看起來可能是相同/相似的錯誤:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6676175

所示的堆棧跟蹤是不相同的,但它提到,其中固定在6u14 revoke_and_rebias一種罕見的競爭狀態。

EDIT4 - 賞金消息應該說「熟悉的熱點實現」

回答

4

VM generated stub frame只是意味着正在執行的代碼已經被JVM產生。

堆棧本身(來自gdb)顯示虛擬機試圖達到一個安全點,因爲它正在撤銷一個偏置鎖。您可以在this blog中閱讀關於偏向鎖定的內容。這意味着某個線程已經獲得了一個監視器,該監視器將該監視器偏向該線程。後來其他一些線程想要鎖,所以它必須撤銷偏好,這需要達到一個安全點(即沒有線程正在執行字節代碼,也就是停止世界)。

您的錯誤也可能表示JVM在某些方法去優化期間崩潰。這意味着JVM已經優化(編譯)了某些方法,但隨後遇到了代碼路徑,導致它需要去優化,因爲編譯的方法不再有效。如果沒有JVM升級,您不太可能找到解決辦法。

看起來你有2種解決方法,你可能想嘗試

  1. ,如果它是由偏向鎖驅動,將其關閉(-XX:-UseBiasedLocking
  2. ,如果它是由deoptimisation驅動,找到有問題的方法,並告訴熱點不首先編譯它,關於如何做到這一點的說明this link

這兩種方法都可能會對性能產生影響。

注意,如果您能夠制定可靠地再現問題的測試場景,那麼這將不那麼令人沮喪。

+0

「的意思是正在執行已經由JVM生成的代碼,即編譯的(優化的)碼」 - 的JVM設法名「org.myapp.AppClass.getBytes()」儘管它是一個編譯的方法(按照標記「J」)。 JVM有時無法命名正在執行的方法?或者,「BufferBlob :: Interpreter」這行代表JVM插入到我的程序中的隱式工作位? – mchr

+1

我編輯了這一點,因爲它不是我想說的。據我所知,一個簡單的編譯方法仍然顯示爲J。 Interpreter行確實引用了JVM創建的代碼。 JVM確實做了很多事情(GC,優化),其他的運行你的代碼。 – Matt

+0

嗯,這是有道理的,但我相當肯定,我的方法在堆棧(org.myapp.AppClass.getBytes())不做任何鎖定。這就是爲什麼我假定BufferBlob :: Interpreter行必須代表更多的方法調用。這可能嗎?我認爲GC和JIT發生在他們自己的線程中。 – mchr

相關問題