zoukankan      html  css  js  c++  java
  • TroubleshootingGuide for JavaTM SE 6withHotSpot TM VM (翻译附录未完待续)2 规格严格

    C.4 线程部分格式

    本节主要描述当JVM crash时候线程的信息。如果多线程在同一时刻crash,只有一个线程的信息会被打印出来。

    C.4.1 线程信息


    线程部分第一部分描述了引起严重错误的线程信息,如下所示:
    Current thread (0x0805ac88): JavaThread "main" [_thread_in_native, id=21139]
                        |             |             |             |                 +-- ID线程ID
                        |             |            |             +------------- state线程状态
                        |             |            +-------------------------- name线程名称
                        |             +------------------------------------ type线程类型
                        +--------------------------------------------------pointer计数器

    线程计数器是指向JVM内部线程结构,如果你不想调试正在运行的JVM或者core文件的话,则该指针没有什么用处。

    下面列出了可能的JVM线程类型
    JavaThread
    VMThread
    CompilerThread
    GCTaskThread
    WatcherThread
    ConcurrentMarkSweepThread        

    译注:具体线程含义还需要查看Oracle官方文档,但是具体也能见名知意。

    下面列举了线程可能的状态:
    线程                    描述
    _thread_uninitialized   线程没有创建,这只会出现在内存错误的前提下
    _thread_new             线程被创建了,但是没有被start
    _thread_in_native       线程运行在本地方法中,这意味着可能在本地代码存在Bug
    _thread_in_vm           线程运行JVM代码
    _thread_in_Java         线程运行在解释模式或者编译模式Java代码
    _thread_blocked         线程被阻塞
    _thread_trans           如果上面任何状态后面跟着这个标志,意味着线程在改变运行状态

    在该输出中的线程ID代表一个本地线程标识(注:这应该jmm里面的,目前没到那种程度分析)
    如果Java线程是dameon的话,则dameon会在线程状态前打印

    C.4.2 信号信息


    在错误日志下一部分信息是导致JVM终止的信号信息,在Windows平台下,输出如下所示:
    siginfo: ExceptionCode=0xc0000005, reading address 0xd8ffecf1
    在上述例子中,错误码是0xc0000005(ACCESS_VIOLATION),并且错误发生在线程试图读取地址
    0xd8ffecf1
    在Solaris或者Linux系统中,信号数字和信号码(这个有点糊涂)被用来识别异常信息,如下所示:
    siginfo:si_signo=11, si_errno=0, si_code=1, si_addr=0x00004321

    C.4.3 寄存器内容


    错误日志的下一部分描述了错误发生时候寄存器的内容,具体输出格式和硬件架构相关,下面的例子描述在IA32下的输出内容:

    Registers:
    EAX=0x00004321, EBX=0x41779dc0, ECX=0x080b8d28, EDX=0x00000000
    ESP=0xbfffc1e0, EBP=0xbfffc1f8, ESI=0x4a6b9278, EDI=0x0805ac88
    EIP=0x417789d7, CR2=0x00004321, EFLAGS=0x00010216

    寄存器内容可以和即将描述的指令结合起来,这是十分有用的对于指令排查

    C.4.4 指令


    在输出寄存器值后,错误日志包含了栈顶上的指令集合(128个字节码操作集合)在程序计数器PC附近,当JVM崩溃的时候。这些字节码可以被汇编器解码成对应的字节码指令,注意IA32和AMD64指令在长度上不一致,因此并不是每次都能解码成功(注:难道AMD64上有可能解析不出来?)

    Top of Stack: (sp=0xbfffc1e0)
    0xbfffc1e0: 00000000 00000000 0818d068 00000000
    0xbfffc1f0: 00000044 4a6b9278 bfffd208 41778a10
    0xbfffc200: 00004321 00000000 00000cd8 0818d328
    0xbfffc210: 00000000 00000000 00000004 00000003
    0xbfffc220: 00000000 4000c78c 00000004 00000000
    0xbfffc230: 00000000 00000000 00180003 00000000
    0xbfffc240: 42010322 417786ec 00000000 00000000
    0xbfffc250: 4177864c 40045250 400131e8 00000000
    Instructions: (pc=0x417789d7)
    0x417789c7: ec 14 e8 72 ff ff ff 81 c3 f2 13 00 00 8b 45 08
    0x417789d7: 0f b6 00 88 45 fb 8d 83 6f ee ff ff 89 04 24 e8

    C.4.5 线程堆栈


    大部分情况下,错误日志的下一部分是线程堆栈,这包含栈帧的栈顶和栈底也就是SP和BP的地址,当前栈指针(这个稍微有点不明白),以及没有被当前线程使用堆栈内存数量。随后的就是栈帧的详细调用信息,最多100个栈帧会被打印出来。对于C/C++栈帧,库名也会被打印出来。需要记住的是,在某些错误情形下,栈帧可能已经破损,因此相应的详细信息可能不会被完全打印出来。

    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]
    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]
    C [java.exe+0x14c0]
    C [java.exe+0x64cd]
    C [kernel32.dll+0x214c7]
    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

    上面的日志包含两类线程堆栈栈帧

    1、第一种是本地栈帧,它会打印出本地线程所有的方法调用,然而这类线程堆栈并没有把运行时inline的Java方法包括进去,因此如果方法被inline的话,则该方法会成为父栈帧的一部分。
    在本地栈帧中的方法信息为调查JVM crash提供了重要的信息,通过分析上述列表中列举的库名称,你能够推断出那个库导致错误出现,并且将该信息报告给库的开发人员。
    2、第二种是Java堆栈,这会打印出Java方法堆栈包括inline的方法,不包含本地堆栈,根据crash的结果,有可能打不出本地堆栈,而打出Java堆栈

    C.4.6 进一步的信息


    如果错误发生在VM线程或者一个compile线程中,更进一步的信息会被打印出来。例如,考虑VM线程的情况,如果VM线程正在执行一个VM操作的时候,如果此时错误发生,则该操作会被打印出来。在下面的输出例子中,compiler线程触发了一个错误,此时HotSpot client虚拟机正在编译一个方法,方法是hs101t004Thread.ackermann
    Current CompileTask:
    HotSpot Client Compiler:754 b
    nsk.jvmti.scenarios.hotswap.HS101.hs101t004Thread.ackermann(IJ)J (42 bytes)

    对于HotSpot Server虚拟机,该compile线程输出的结果略微不同,但也会包含完整的类名和方法名称。


    译注:这节翻译的很晦涩,有些概念自己理解的也是模棱两可,望大家见谅和指正。
  • 相关阅读:
    《小C QQ空间转帖、分享工具》之QQ空间数据传递的g_tk算法(C#)
    2.线性回归
    1(3).频率派 VS 贝叶斯派
    sklearn---SVM
    sklearn总览
    word转pdf时图片质量下降的解决方案
    python-字符串前面添加u,r,b的含义
    matplotlib---保存图片出现的问题
    matplotlib---设置线条颜色及形状
    numpy中arange()和linspace()区别
  • 原文地址:https://www.cnblogs.com/diyunpeng/p/2380539.html
Copyright © 2011-2022 走看看