RFR: 8292699: Improve printing of classes in native debugger [v5]
Thomas Stuefe
stuefe at openjdk.org
Mon Aug 22 05:31:39 UTC 2022
On Sun, 21 Aug 2022 22:02:34 GMT, Ioi Lam <iklam at openjdk.org> wrote:
>> Current in gdb, you can print information about a class or method with something like
>>
>>
>> call ((InstanceKlass*)0x00000008000411b8)->print_on(tty)
>> call ((Method*)0x00007fffb4000d08)->print_codes_on(tty)
>>
>>
>> However, it's difficult to find a class or method by its name and print out its contents.
>>
>> This RFE adds 3 new functions in debug.cpp so you can easily find classes/methods and print out their contents. They all have a `flags` argument that controls the verbosity.
>>
>> - `findclass()`: class name only
>> - `findmethod()`: class name and method name
>> - `findmethod2()`: class name and method name/signature
>>
>> I also cleaned up `BytecodeTracer` to remove unnecessary complexity.
>>
>> Here are some examples:
>>
>>
>> (gdb) call findclass("java/lang/Object", 0)
>> [0] 0x00000008000411b8 java.lang.Object, loader data: 0x00007ffff0130d10 of 'bootstrap'
>>
>> (gdb) call findclass("java/lang/Object", 1)
>> [0] 0x00000008000411b8 java.lang.Object, loader data: 0x00007ffff0130d10 of 'bootstrap'
>> 0x00007fffb4000658 <init> : ()V
>> 0x00007fffb40010f0 finalize : ()V
>> 0x00007fffb4000f00 wait0 : (J)V
>> 0x00007fffb40008e8 equals : (Ljava/lang/Object;)Z
>> 0x00007fffb4000aa0 toString : ()Ljava/lang/String;
>> 0x00007fffb40007f0 hashCode : ()I
>> 0x00007fffb4000720 getClass : ()Ljava/lang/Class;
>> 0x00007fffb40009a0 clone : ()Ljava/lang/Object;
>> 0x00007fffb4000b50 notify : ()V
>> 0x00007fffb4000c20 notifyAll : ()V
>> 0x00007fffb4000e50 wait : (J)V
>> 0x00007fffb4001028 wait : (JI)V
>> 0x00007fffb4000d08 wait : ()V
>>
>> (gdb) call findclass("*ClassLoader", 0)
>> [0] 0x000000080007de40 jdk.internal.loader.ClassLoaders$BootClassLoader, loader data: 0x00007ffff0130d10 of 'bootstrap'
>> [1] 0x0000000800053c58 jdk.internal.loader.ClassLoaders$PlatformClassLoader, loader data: 0x00007ffff0130d10 of 'bootstrap'
>> [2] 0x0000000800053918 jdk.internal.loader.ClassLoaders$AppClassLoader, loader data: 0x00007ffff0130d10 of 'bootstrap'
>> [....]
>>
>> (gdb) call findmethod2("*ang/Object*", "wait", "()V", 0x7)
>> [0] 0x00000008000411b8 java.lang.Object, loader data: 0x00007ffff0130d10 of 'bootstrap'
>> 0x00007fffb4000d08 wait : ()V
>> 0x00007fffb4000ce8 0 fast_aload_0
>> 0x00007fffb4000ce9 1 lconst_0
>> 0x00007fffb4000cea 2 invokevirtual 38 <java/lang/Object.wait(J)V>
>> 0x00007fffb4000ced 5 return
>
> Ioi Lam has updated the pull request incrementally with one additional commit since the last revision:
>
> also print Method pointer
Hi Ioi,
this looks neat. Not a full review, just some remarks:
- Not your patch, but while playing with this I found that "call help()" needs a RM, which means gdb crashes out in a non-attached thread (e.g. the primordial one). Would be nice if no RM were needed.
- Calling "findclass" from a java thread yielded this:
(gdb) call findclass("*", 7)
[Thread 0x7fffb28cf700 (LWP 112211) exited]
"Executing findclass"
Thread 2 "java" received signal SIGSEGV, Segmentation fault.
0x00007ffff6fe17ba in assert_locked_or_safepoint (lock=0x7ffff0027320) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/runtime/mutexLocker.cpp:178
178 fatal("must own lock %s", lock->name());
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function
(findclass(char const*, int)) will be abandoned.
When the function is done executing, GDB will silently stop.
(gdb) bt
#0 0x00007ffff6fe17ba in assert_locked_or_safepoint (lock=0x7ffff0027320) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/runtime/mutexLocker.cpp:178
#1 assert_locked_or_safepoint (lock=0x7ffff0027320) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/runtime/mutexLocker.cpp:172
#2 0x00007ffff639dcfb in ClassLoaderDataGraphIteratorBase<true>::ClassLoaderDataGraphIteratorBase (this=0x7ffff57b3390) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/runtime/handles.hpp:263
#3 ClassLoaderDataGraph::classes_do (klass_closure=klass_closure at entry=0x7ffff57b3420) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/classfile/classLoaderDataGraph.cpp:366
#4 0x00007ffff63acbe0 in ClassPrinter::print_classes_unlocked (class_name_pattern=class_name_pattern at entry=0x7ffff7d5de80 "*", flags=flags at entry=7) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/classfile/classPrinter.cpp:139
#5 0x00007ffff64ebda9 in findclass (class_name_pattern=0x7ffff7d5de80 "*", flags=7) at /shared/projects/openjdk/jdk-jdk/source/src/hotspot/share/utilities/debug.cpp:647
#6 <function called from gdb>
#7 __GI___libc_read (nbytes=8192, buf=0x7ffff57b3600, fd=0) at ../sysdeps/unix/sysv/linux/read.c:26
#8 __GI___libc_read (fd=fd at entry=0, buf=buf at entry=0x7ffff57b3600, nbytes=nbytes at entry=8192) at ../sysdeps/unix/sysv/linux/read.c:24
#9 0x00007ffff5682038 in read (__nbytes=8192, __buf=0x7ffff57b3600, __fd=0) at /usr/include/x86_64-linux-gnu/bits/unistd.h:44
#10 handleRead (fd=fd at entry=0, buf=buf at entry=0x7ffff57b3600, len=len at entry=8192) at /shared/projects/openjdk/jdk-jdk/source/src/java.base/unix/native/libjava/io_util_md.c:188
#11 0x00007ffff568178c in readBytes (env=0x7ffff0029170, this=<optimized out>, bytes=0x7ffff57b56e8, off=0, len=8192, fid=<optimized out>) at /shared/projects/openjdk/jdk-jdk/source/src/java.base/share/native/libjava/io_util.c:109
#12 0x00007fffe01eaf50 in ?? ()
#13 0x0000000000000040 in ?? ()
#14 0x00007ffff0028e50 in ?? ()
#15 0x00007fffa802f620 in ?? ()
```
- You could add a simple test at least as gtests, looking for some well-known classes.
- instead of using int for flags, maybe use an enum class and define the bitwise combine operator? Like this:
enum class Mode : int {
PRINT_METHOD_NAME = 1 << 0,
PRINT_BYTECODE = 1 << 1,
PRINT_BYTECODE_ADDR = 1 << 2,
PRINT_DYNAMIC = 1 << 3, // extra information for invokedynamic (and dynamic constant ...)
};
constexpr enum Mode operator | (enum Mode selfValue, enum Mode inValue) { return (Mode)(uint32_t(selfValue) | uint32_t(inValue)); }
Cheers, Thomas
src/hotspot/share/classfile/classPrinter.hpp line 59:
> 57: };
> 58:
> 59: // flags must be OR'ed from ClassPrinter::Mode for the next 3 functions
Can you give us a mode PRINT_ALL that or'es all of them modes together, and make that maybe the default for flags?
-------------
PR: https://git.openjdk.org/jdk/pull/9957
More information about the hotspot-dev
mailing list