从JVM致命错误日志中猜测方法行号 [英] Guess method line number from JVM fatal error log

查看:136
本文介绍了从JVM致命错误日志中猜测方法行号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个没有核心转储的致命错误日志,需要确定原因. 这是在.log文件中找到的堆栈:

I have a fatal error log without a core-dump and need to identify the cause. This is the stack found in the .log file:

# Problematic frame:
# C  [libc.so.6+0x7b4bb]  memcpy+0x15b

{...}

Stack: [0x00002ac8c4d2c000,0x00002ac8c4e2d000],  sp=0x00002ac8c4e28ef8,  free space=1011k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [libc.so.6+0x7b4bb]  memcpy+0x15b
C  [libzip.so+0x50b0]  ZIP_GetEntry+0xd0
C  [libzip.so+0x3eed]  Java_java_util_zip_ZipFile_getEntry+0xad
J 28  java.util.zip.ZipFile.getEntry(J[BZ)J (0 bytes) @ 0x00002ac8acf404ee [0x00002ac8acf40420+0xce]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J 28  java.util.zip.ZipFile.getEntry(J[BZ)J (0 bytes) @ 0x00002ac8acf40478 [0x00002ac8acf40420+0x58]
J 33 C2 java.util.zip.ZipFile.getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry; (86 bytes) @ 0x00002ac8acf45548 [0x00002ac8acf45480+0xc8]
J 58 C2 java.util.jar.JarFile.getJarEntry(Ljava/lang/String;)Ljava/util/jar/JarEntry; (9 bytes) @ 0x00002ac8acf4e828 [0x00002ac8acf4e7e0+0x48]
J 44 C2 sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource; (91 bytes) @ 0x00002ac8acf47168 [0x00002ac8acf47100+0x68]
J 34 C2 sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource; (74 bytes) @ 0x00002ac8acf41f70 [0x00002ac8acf41f00+0x70]
j  java.net.URLClassLoader$1.run()Ljava/lang/Class;+26
j  java.net.URLClassLoader$1.run()Ljava/lang/Object;+1
v  ~StubRoutines::call_stub
j  java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+0
j  java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;+13
j  java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+70
j  sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+36
j  java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3
v  ~StubRoutines::call_stub
j  com.smackdapp.SmackHandler.handleRequest(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V+72

正如我在另一个StackOverflow答案中所读到的那样,这可能是替换jvm需要加载的任何.jar(或硬件内存错误)时的常见错误.

As I have read in another StackOverflow answers, this can be a common error while replacing any .jar that the jvm needs to load (or a hardware memory error).

我想猜测的是导致此致命错误的.jar文件.是否可以通过致命错误日志中的信息来识别源代码中的行号?

What I'm trying to guess is the .jar file that caused this fatal error. Is there any way to identify the line number in my source code with the information in the fatal error log?

我希望此行末的"V + 72"有事可做,但无法弄清楚.

I was hoping that this "V+72" at the end of the line has something to do, but can't figure out.

推荐答案

最终,这可能无助于解决问题,但它回答了一部分问题:

This may not help to solve the problem, eventually, but it answers a part of the question:

热舔在他的注释中,+72只是字节码偏移量.我用一个小程序对此进行了测试:

As already guessed by Hot Licks in his comment, the +72 just is the bytecode offset. I tested this with a small program:

(否则不相关,只是可以从另一个问题中快速获得它)

class TestNativeArray3D
{
    public static void main(String args[])
    {
        System.loadLibrary("TestNativeArray3D");
        int terrain[][][] = genTerrain(123, 8, 6);
    }
    private native static int[][][] genTerrain(int seed, int x, int y);
}

原生genTerrain函数通过调用公然创建一个任意错误

The native genTerrain function blatantly creates an arbitrary error, by calling

jclass errorClass = env->FindClass("XXX");
env->NewObjectArray(10, errorClass, NULL);

导致核心转储.

堆栈如下所示:

Stack: [0x0000000002500000,0x0000000002600000],  sp=0x00000000025ff4e0,  free space=1021k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x14ebb6]
C  [TestNativeArray3D.dll+0x397d]  JNIEnv_::NewObjectArray+0x4d
C  [TestNativeArray3D.dll+0x3ae8]  Java_TestNativeArray3D_genTerrain+0x98
C  0x0000000002715534

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  TestNativeArray3D.genTerrain(III)[[[I+0
j  TestNativeArray3D.main([Ljava/lang/String;)V+11
v  ~StubRoutines::call_stub

在这里,类似地包含(可能)偏移量的行是

Here, the line that analogously contains the (possible) offset is

j TestNativeArray3D.main([Ljava/lang/String;)V +11

j TestNativeArray3D.main([Ljava/lang/String;)V+11

使用

反编译class文件时

javap -c -l TestNativeArray3D

(请注意-l(小"L")以获得行号!)输出为

(note the -l (small "L") to obtain the line numbers!) the output is

class TestNativeArray3D {
  TestNativeArray3D();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
    LineNumberTable:
      line 3: 0

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String TestNativeArray3D
       2: invokestatic  #3                  // Method java/lang/System.loadLibrary:(Ljava/lang/String;)V
       5: bipush        123
       7: bipush        8
       9: bipush        6
      11: invokestatic  #4                  // Method genTerrain:(III)[[[I
      14: astore_1
      15: return
    LineNumberTable:
      line 7: 0
      line 8: 5
      line 9: 15
}

,实际上,本地调用发生在偏移量11处. (是的,我在此调用之前通过添加一些其他代码进行了反检查:核心转储中的偏移量相应地发生了变化).

and indeed, the native call happens at offset 11. (And yes, I counter-checked this by adding some further code before this call: The offset in the core dump changes accordingly).

"LineNumberTable"将允许您在字节码偏移量和行之间进行映射.示例中的表格表示

The "LineNumberTable" will allow you to map between bytecode offsets and lines. The table in the example means that

  • 源代码行7对应于字节码偏移量0,
  • 源代码行8对应于字节码偏移量5,
  • 源代码行9对应于字节码偏移量15

所以这里的关键指令与代码行8有关.(在这种情况下,这很明显,因为这直接是invokestatic调用.我只想指出,您可以查找LineNumberTable进行映射相对于源代码中实际行 number 的字节代码的偏移量)

so the critical instruction here is related to code line 8. (This was obvious, in this case, because this was directly the invokestatic call. I just wanted to point out that you can look up the LineNumberTable for the mapping of the bytecode offset to the actual line number in the source code)

不幸的是,这几乎不能帮助您真正解决错误,因为该错误显然是在libc.so的本机代码中在某些memcpy期间引起了更深的层次-显然从libzip.so ...

Unfortunately, this will hardly help you to really solve the error, because this one was obviously caused some levels deeper, in the native code of libc.so, during some memcpy - which obviously received invalid pointers from the libzip.so...

这篇关于从JVM致命错误日志中猜测方法行号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆