Java-Kern: GDB + Python (openjdk Unwinder)

Überprüfen Sie den Kern von Java VM mit gdb.

Originalgeschichte, http://icedtea.classpath.org/people/adinn/unwinder/file/f50e52519fb9/ java calling convention Es wird als aufrufende Konvention festgelegt, welches Register das Argument beim Aufrufen der Funktion im Programm setzen soll und wo im Stapel die Rückgabezieladresse gesetzt ist. In ähnlicher Weise gibt es in Java VM eine Aufrufkonvention in Java VM, wenn eine Methode in einem Java-Programm aufgerufen wird, die sich vollständig von der x86-64-Aufrufkonvention unterscheidet. Wenn Sie die Kerndatei von Java VM mit gdb öffnen, wird daher der Stapel des nativen Teils von x86-64 angezeigt, aber die Stapelinformationen werden mit der Notation ?? für den Java-Stapel nicht korrekt angezeigt. Mit OpenJDK Unwinder ist es möglich, den Java VM-Stack mit gdb anzuzeigen. OpenJDK Unwinder

(gdb) source dbg8.py
Installing openjdk unwinder
(gdb) bt
#0  0x00007f17a5f2970d in read () at /lib64/libpthread.so.0
#1  0x00007f17a372b7b8 in  () at /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/lib/amd64/libjava.so
#2  0x00007f17a372ae28 in  () at /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/lib/amd64/libjava.so
#3  0x00007f178d017774 in [native] java.io.FileInputStream.readBytes(byte,int,int) () at java/io/FileInputStream.java
#4  0x00007f178d007a40 in [interpreted: bc = 4] java.io.FileInputStream.read(byte,int,int) ()
    at java/io/FileInputStream.java:255
#5  0x00007f178d007a40 in [interpreted: bc = 39] java.io.BufferedInputStream.read1(byte,int,int) ()
    at java/io/BufferedInputStream.java:286
#6  0x00007f178d007a40 in [interpreted: bc = 49] java.io.BufferedInputStream.read(byte,int,int) ()
    at java/io/BufferedInputStream.java:346
#7  0x00007f178d007a40 in [interpreted: bc = 135] sun.nio.cs.StreamDecoder.readBytes() ()
    at sun/nio/cs/StreamDecoder.java:285
#8  0x00007f178d007a40 in [interpreted: bc = 112] sun.nio.cs.StreamDecoder.implRead(char,int,int) ()
    at sun/nio/cs/StreamDecoder.java:327
#9  0x00007f178d007a40 in [interpreted: bc = 180] sun.nio.cs.StreamDecoder.read(char,int,int) ()
    at sun/nio/cs/StreamDecoder.java:179
#10 0x00007f178d007a40 in [interpreted: bc = 7] java.io.InputStreamReader.read(char,int,int) ()
    at java/io/InputStreamReader.java:184
#11 0x00007f178d007a40 in [interpreted: bc = 145] java.io.BufferedReader.fill() () at java/io/BufferedReader.java:162
#12 0x00007f178d007ffd in [interpreted: bc = 44] java.io.BufferedReader.readLine(boolean) ()
    at java/io/BufferedReader.java:325
#13 0x00007f178d007d80 in [interpreted: bc = 2] java.io.BufferedReader.readLine() ()
    at java/io/BufferedReader.java:389
#14 0x00007f178d007d80 in [interpreted: bc = 27] sleep.keyin() () at sleep.java:33
#15 0x00007f178d007ffd in [interpreted: bc = 9] sleep.main(java.lang.String) () at sleep.java:14
#16 0x00007f178d0004e7 in StubRoutines (1) ()
#17 0x00007f17a4be3b4a in JavaCalls::call_helper(JavaValue*, methodHandle*, JavaCallArguments*, Thread*) (result=0x7f17a633dce0, m=<optimized out>, args=<optimized out>, __the_thread__=0x7f179c009000)
    at /usr/src/debug/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/openjdk/hotspot/src/share/vm/runtime/javaCalls.cpp:406
#18 0x00007f17a4bf51ea in jni_invoke_static(JNIEnv*, JavaValue*, jmethodID, JNI_ArgumentPusher*, Thread*, JNICallType, jobject) (env=env@entry=0x7f179c009258, result=result@entry=0x7f17a633dce0, method_id=method_id@entry=0x7f179c0d9980, args=args@entry=0x7f17a633dd30, __the_thread__=__the_thread__@entry=0x7f179c009000, call_type=JNI_STATIC, receiver=0x0, this=<optimized out>)
    at /usr/src/debug/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/openjdk/hotspot/src/share/vm/prims/jni.cpp:1330
#19 0x00007f17a4c08ee6 in jni_CallStaticVoidMethod(JNIEnv*, jclass, jmethodID, ...) (env=0x7f179c009258, cls=<optimized out>, methodID=0x7f179c0d9980)
    at /usr/src/debug/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/openjdk/hotspot/src/share/vm/prims/jni.cpp:2524
#20 0x00007f17a5af99e9 in  ()
    at /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/bin/../lib/amd64/jli/libjli.so
#21 0x00007f17a5f22e25 in start_thread () at /lib64/libpthread.so.0
#22 0x00007f17a562734d in clone () at /lib64/libc.so.6
(gdb) 

Normalerweise, wenn Sie bt mit gdb tun, wird es von der Mitte sein, wie unten gezeigt.

(gdb) bt
#0  0x00007f17a5f2970d in read () from /lib64/libpthread.so.0
#1  0x00007f17a372b7b8 in read (__nbytes=8192, __buf=0x7f17a633b2f0, __fd=0) at /usr/include/bits/unistd.h:44
#2  handleRead (fd=0, buf=buf@entry=0x7f17a633b2f0, len=len@entry=8192)
    at /usr/src/debug/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/openjdk/jdk/src/solaris/native/java/io/io_util_md.c:156
#3  0x00007f17a372ae28 in readBytes (env=0x7f179c009258, this=0x7f17a633d3d8, bytes=0x7f17a633d3d0, off=0, len=8192, 
    fid=<optimized out>)
    at /usr/src/debug/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/openjdk/jdk/src/share/native/java/io/io_util.c:109
#4  0x00007f178d017774 in ?? ()
#5  0x00007f17a0406570 in ?? ()
#6  0x00007f179c009000 in ?? ()
#7  0x00007f17a0407260 in ?? ()
#8  0x00007f179c009000 in ?? ()
#9  0x00007f17a633d360 in ?? ()
#10 0x0000000000000000 in ?? ()
(gdb) 

In jstack

Sie können native Stacks wie __libc_read auch mit der Option jstack "-m" anzeigen. Viele Leute möchten sich jedoch bei der GDB erkundigen, mit der sie vertraut sind. ..

$ jstack -m  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/bin/java ./core.6688
...Unterlassung...
----------------- 6689 -----------------
0x00007f17a5f2970d      __libc_read + 0x2d
0x00007f17a372ae28      readBytes + 0x188
0x00007f178d017774      * java.io.FileInputStream.readBytes(byte[], int, int) bci:0 (Interpreted frame)
0x00007f178d007a40      * java.io.FileInputStream.read(byte[], int, int) bci:4 line:255 (Interpreted frame)
0x00007f178d007a40      * java.io.BufferedInputStream.read1(byte[], int, int) bci:39 line:284 (Interpreted frame)
0x00007f178d007a40      * java.io.BufferedInputStream.read(byte[], int, int) bci:49 line:345 (Interpreted frame)
0x00007f178d007a40      * sun.nio.cs.StreamDecoder.readBytes() bci:135 line:284 (Interpreted frame)
0x00007f178d007a40      * sun.nio.cs.StreamDecoder.implRead(char[], int, int) bci:112 line:326 (Interpreted frame)
0x00007f178d007a40      * sun.nio.cs.StreamDecoder.read(char[], int, int) bci:180 line:178 (Interpreted frame)
0x00007f178d007a40      * java.io.InputStreamReader.read(char[], int, int) bci:7 line:184 (Interpreted frame)
0x00007f178d007a40      * java.io.BufferedReader.fill() bci:145 line:161 (Interpreted frame)
0x00007f178d007ffd      * java.io.BufferedReader.readLine(boolean) bci:44 line:324 (Interpreted frame)
0x00007f178d007d80      * java.io.BufferedReader.readLine() bci:2 line:389 (Interpreted frame)
0x00007f178d007d80      * sleep.keyin() bci:27 line:29 (Interpreted frame)
0x00007f178d007ffd      * sleep.main(java.lang.String[]) bci:9 line:14 (Interpreted frame)
0x00007f178d0004e7      <StubRoutines>
0x00007f17a4be3b4a      _ZN9JavaCalls11call_helperEP9JavaValueP12methodHandleP17JavaCallArgumentsP6Thread + 0xf0a
0x00007f17a4bf51ea      _ZL17jni_invoke_staticP7JNIEnv_P9JavaValueP8_jobject11JNICallTypeP10_jmethodIDP18JNI_ArgumentPusherP6Thread.isra.201 + 0x30a
0x00007f17a4c08ee6      jni_CallStaticVoidMethod + 0x186
0x00007f17a5af99e9      JavaMain + 0xa29

Einrichten der GDB-Ausführungsumgebung

In der Umgebung von RHEL 7.4 wurde zusätzlich Folgendes installiert.

# yum install java-1.8.0-openjdk-debuginfo-1.8.0.131-11.b12.el7.x86_64
# yum install xz-devel-5.2.2-1.el7.x86_64 
# yum install python-devel-2.7.5-58.el7.x86_64

--gdb machen

OpenJDK Unwinder nutzt die seit GDB 7.10 unterstützten Frame Uninder-Funktionen von Python. Die in RHEL 7.4 enthaltene GDB ist so alt wie GDB-7.6.1 und erfordert eine neuere Version von GDB. Laden Sie es wie folgt herunter und kompilieren Sie es.

# mkdir /work
# cd /work 
# wget https://ftp.gnu.org/gnu/gdb/gdb-7.12.tar.xz
# tar xvf gdb-7.12.tar.xz
# cd /work/gdb-7.12
# ./configure --with-python --with-lzma
# make

Die neu erstellte GDB kann libjvm.so.debug nicht finden. Erstellen Sie daher einen symbolischen Link.

# ln -s /usr/lib/debug/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/lib/amd64/server 
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/lib/amd64/server/.debug

--Bring OpenJDK Unwinder.

http://icedtea.classpath.org/people/adinn/unwinder/file/f50e52519fb9/ (Ich habe den angezeigten Inhalt von dbg8.py nach dbg8.py kopiert.)

Führen Sie gdb aus

$  /work/gdb-7.12/gdb/gdb  --data-directory=/work/gdb-7.12/gdb/data-directory  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/bin/java ./core.6688
...Unterlassung...
(gdb) source dbg8.py
Installing openjdk unwinder
(gdb) thread 1
(gdb) bt
Die Stapelinformationen einschließlich des zu Beginn erwähnten Java-Frames werden angezeigt.

Ich bin süchtig nach GDB

(gdb) source dbg8.py Traceback (most recent call last): File "dbg8.py", line 21, in import gdb ImportError: No module named gdb (gdb)

Da die zu importierende GDB nicht in Python gefunden wird, ist es in Ordnung, wenn Sie beim Starten von GDB "--data-directory = / work / gdb-7.12 / gdb / data-directory" angeben.

(gdb) source dbg8.py Installing openjdk unwinder Traceback (most recent call last): File "dbg8.py", line 52, in class Types(object): File "dbg8.py", line 66, in Types nmethodp_t = gdb.lookup_type('nmethod').pointer() gdb.error: No type named nmethod. (gdb)

gdb kann die Datei libjvm.so.debug nicht finden. Überprüfen Sie, nach welchem Verzeichnis gdb mit strace usw. sucht, und fügen Sie dort libjvm.so.debug ein, oder erstellen Sie einen symbolischen Link wie das Anpassen des Pfads von libjvm.so.debug über OK

Wenn Sie gdb in einer Umgebung erstellen, in der xz-devel-5.2.2-1.el7.x86_64 nicht installiert ist, wird beim Start von gdb die folgende Warnung angezeigt. Machen Sie nach der Installation von xz-devel gdb und es ist OK.

warning: Cannot parse .gnu_debugdata section; LZMA support was disabled at compile time

Recommended Posts

Java-Kern: GDB + Python (openjdk Unwinder)
Java VS PHP VS Python VS Ruby
Ich habe Java und Python verglichen!