JVMクラッシュログのBufferBlob :: Interpreterはどういう意味ですか?

私は時々私のアプリケーションで発生するJVMのクラッシュを調べています。 hs_errファイルには、クラッシュに関する以下の詳細が含まれています。

#  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)

これは、Javaコードを実行しているときにJVMがセグメンテーション違反を起こしたことを示しています。エラーログには、クラッシュしたスレッドのスタックに関する情報も含まれています。

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  
#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

これは、元のバグレポートに記載されている6つのlibjvm.soフレームが、Javaロックの取得に関連していることを示しています。しかし、ロックを使用するorg.myapp.AppClass.getBytes()内にコードが見つかりません。

スタック内のBufferBlob :: Interpreter行は何を意味しますか?これらのJavaスタックフレームはありますか? JVMスタックフレーム?これらのスタックフレームで呼び出されていたものを解決することは可能ですか?

注:私は新しいホットスポットJVMに切り替えることをお勧めしないでください。私はCMSコレクタに依存しており、最近のV1.6ホットスポット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フレーム"のリストのBufferBlob :: Interpreterの5行ときれいに一致します。

これは新しい質問をいくつか提起します:

  • 「ネイティブフレーム」の下にある5行のBufferBlob :: Interpreterが、 セクションは、 "Java frames"セクションの下にある同じ行と重複していますか?
  • エラーログにこれらの5つのスタックフレームの詳細が表示されないのはなぜですか?

EDIT3 - This Oracle bug looks likely to be the same/similar bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6676175

示されているスタックトレースは同じではありませんが、6u14で修正されたrevoke_and_rebiasのまれな競合状態に言及しています。

EDIT4 - 賞金のメッセージは "ホットスポットの実装に精通している"

7

2 答え

VM generated stub frame just means that the code that is executing has been generated by the JVM.

スタック自体(gdbから)は、バイアスされたロックを取り消しているため、VMがセーフポイントに到達しようとしていることを示しています。バイアスされたロックについては、このブログを参照してください。これは、あるスレッドが、そのスレッドに向かってそのモニターを偏らせるモニターを取得したことを意味します。後で他のスレッドがロックを望むので、セーフポイントに達することを要求するバイアスを取り消さなければならない(すなわち、スレッドは世界を止める別のバイトコードを実行していない)。

あなたのエラーは、いくつかの方法の最適化を解除している間にJVMがクラッシュすることを示している可能性もあります。つまり、JVMは特定のメソッドを既に最適化(コンパイル)していますが、コンパイルされたメソッドはもはや有効ではないため、最適化を解除する必要があるコードパスにヒットします。 JVMのアップグレードがなければ、これに対する修正を見つけることはまずありません。

あなたが試してみたいかもしれない2つの回避策があるようです

  1. if it's driven by biased locking, turn it off (-XX:-UseBiasedLocking)
  2. if it's driven by deoptimisation, find the offending method and tell hotspot not to compile it in the first place, instructions on how to do this on this link

どちらの方法もパフォーマンスに影響を与える可能性があります。

問題を確実に再現するテストシナリオを試すことができれば、これはあまりイライラしません。

4
追加された
実行中のコードがJVMによって生成された、つまりコンパイルされた(最適化された)コードを意味する " - JVMはコンパイルされたメソッドであるにもかかわらず、" org.myapp.AppClass.getBytes() "J")。 JVMは、実行中のメソッドに名前を付けることができないことがありますか?または、 "BufferBlob :: Interpreter"行は、JVMが私のプログラムに挿入した暗黙の作業のビットを参照していますか?
追加された 著者 mchr,
Hmmmは意味がありますが、スタック(org.myapp.AppClass.getBytes())内のメソッドがロックを行わないことはかなり確かです。だからこそ、私はBufferBlob :: Interpreter行がさらなるメソッド呼び出しを表現しなければならないと仮定していたのです。これは可能ですか?私はGCとJITが自分のスレッドで起こったと思った。
追加された 著者 mchr,
私はそれが私が言っていたものではないので、そのビットを編集しました。私が知る限り、単純なコンパイルされたメソッドはまだJとして表示されます。インタプリタの行は、JVMが作成したコードを参照します。 JVMは多くのことを行います(GC、最適化)あなたのコードを実行します。
追加された 著者 Matt,
この文書では、最適化が実際にどのように起こるかに関する情報があります。 - cs.princeton.edu/ picasso/mats/HotspotOverview.pdf - ここでバイアスの取り消しの要約 - oracle.com/technetwork/java/javase/tech/… - どちらの場合も、スレッドを強制的に停止させるセーフポイントに到達する必要があります。私はインタプリタのものはインタープリタされたフレームを参照するので、コンパイルされたメソッドから最適化されていないバージョンに切り替えられた可能性があります。私は -XX:+ PrintCompilation を使って何が起こっているのかをもっと詳細に見ていくつもりです。
追加された 著者 Matt,

この質問は、hotspot-runtime-devメーリングリストのTom Rodriguezによって答えられました。

http://mail.openjdk.java.net /pipermail/hotspot-runtime-dev/2011-November/002592.html

1
追加された