Java JVM崩溃日志中的BufferBlob::解释器是什么意思?

Java JVM崩溃日志中的BufferBlob::解释器是什么意思?,java,crash,jvm,gdb,jvm-hotspot,Java,Crash,Jvm,Gdb,Jvm Hotspot,我正在调查我的应用程序中偶尔发生的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) 所以这告诉我JVM在运行一些Java代码时遇到了一个错误。错误日志还包含有关崩溃线程堆栈的信息 Native frames: (J=com

我正在调查我的应用程序中偶尔发生的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)

所以这告诉我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
最后一个方法是获取一个锁。这可能是最终调用上面列出的JVM代码的来源。上面的这个堆栈有一个简洁的特性,即getBytes()下面有5个Java堆栈框架。这将与“Java框架”列表中的5行BufferBlob::解释器完美匹配

这就提出了几个新问题:

  • “本机框架”下的5行BufferBlob::解释器是否可能 部分只是“Java框架”部分下相同行的副本
  • 为什么错误日志没有显示这5个堆栈帧的详细信息
EDIT3-此Oracle错误看起来可能是相同/相似的错误:

所显示的堆栈跟踪不完全相同,但它提到了revoke_和_rebias中的一个罕见竞争条件,该条件在6u14中已修复


EDIT4-赏金消息应该说“熟悉热点实现”

VM生成的存根帧
只意味着正在执行的代码是由JVM生成的

堆栈本身(来自gdb)显示VM正试图达到安全点,因为它正在撤销有偏锁。您可以阅读关于有偏锁定的内容。这意味着某个线程获取了一个监视器,该监视器会将监视器偏向该线程。稍后,另一个线程需要锁,因此它必须撤销需要达到安全点的偏差(即,没有线程正在执行字节码aka stop the world)

您的错误还可能表明JVM在某些方法的去优化过程中崩溃。这意味着JVM已经优化(编译)了某些方法,但随后遇到了一个代码路径,这导致它需要去优化,因为编译后的方法不再有效。如果没有JVM升级,您不可能找到解决方案

看起来您有两种可能需要尝试的变通方法

  • 如果由偏置锁定驱动,请将其关闭(
    -XX:-usebiasedblocking
  • 如果它是由去优化驱动的,那么找到有问题的方法并告诉hotspot不要首先编译它,关于如何在
  • 这两种方法都可能对性能产生影响


    注意:如果您能够制定出一个可靠地再现问题的测试场景,那么这就不会那么令人沮丧了。

    这个问题现在已经由Tom Rodriguez在hotspot runtime dev邮件列表中回答了


    “表示正在执行的代码是由JVM生成的,即编译(优化)代码”-JVM设法命名为“org.myapp.AppClass.getBytes()”,尽管它是一个编译方法(根据标记“J”)。JVM有时是否无法命名正在执行的方法?或者“BufferBlob::解释器”行是指JVM插入到我的程序中的隐式工作位吗?我编辑了该位,因为它不是我想说的。据我所知,一个简单的编译方法仍然以J的形式出现。解释器行确实引用了JVM创建的代码。JVM确实做了很多事情(GC、优化),除了运行你的代码。Hmmm,这是有意义的,只是我非常确定堆栈中的方法(org.myapp.AppClass.getBytes())不会执行任何锁定。这就是为什么我假设BufferBlob::解释器行必须表示进一步的方法调用。这可能吗?我认为GC和JIT是在各自的线程中发生的。本文中提供了一些关于去优化实际如何发生的信息——这里是对偏差撤销的总结——两者都需要达到一个安全点,这意味着强制线程停止。我认为解释器指的是被解释的帧,所以它可能已经从编译的方法切换回了非优化的版本。我倾向于使用
    -XX:+printcomilation
    更详细地了解正在发生的事情。
    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)
    
    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;
    
    #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
    
    AppClass.getBytes()
    AppClass.readByte()
    DataInputStream.readByte()
    SocketInputStream.read()
    SocketInputStream.read(byte[],int,int)
    PlainSocketImpl.aquireFD()