Hi Volker, Happy New Year. I'd like to ask some question about hotspot of openjdk.
volker.simonis at gmail.com
Mon Jan 5 05:50:33 PST 2009
there are some things to consider if you want to debug the HotSpot interpreter:
- gdb should work fairy well, however for some historic reasons, the
debug version of HotSpot on Linux/x86 is built with "-gstabs". To get
a better debugging experience, you should change this to "-g" at the
end of the file "hotspot/make/linux/makefiles/gcc.make" and rebuild
the VM with these new settings.
- in general, the "java" launcher will "execv()" itself to ensure it
has the right LD_LIBRARY_PATH settings but this "execv()" can confuse
gdb. To avoid it, you can either use the "gamma" launcher as explained
in my blog ("gamma" does not execv, because the user is responsible to
set the right LD_LIBRARY_PATH before calling "gamma"). The other
possibility is to set the LD_LIBRARY_PATH manually before running
"java" such that it begins with the prefix expected by the the
launcher. In this case the launcher does not need to do an "execv()".
To achieve this, you can set a breakpoint in
"CreateExecutionEnvironment()" in "src/solaris/bin/java_md.c" (solaris
is no typo here!!!) and check the path the launcher expects to see for
LD_LIBRARY_PATH (look for the value of "newpath").
- even if you followed the two points above, you can not easily set a
breakpoint in the interpreter, because the interpreter is generated at
startup. This means that there are no C-sources for the interpretation
of a bytecode (instead there's C-code which generates code which will
execute a bytecode). You can display the generated interpreter and the
various stubs with the options "-XX:+PrintInterpreter" and
"-XX:+PrintStubCode". You should use this together with
"-XX:+PrintAssembly" to get a disassembly of the generated templates
and stubs. (Notice that you need to compile and use the additional
library "disassembler.so" for this to work. More information on the
disassembler library can be found under:
- I suggest you run the VM once with "-XX:+PrintAssembly
-XX:+PrintInterpreter -XX:+PrintStubCode" and save the output to a
file. You should do this in the debugger, such that the addresses of
the generated code are the same like in the actual debug run. During a
debugging session, you can then always cross check in which generated
part of the interpreter you are. For a HotSpot debug build, you can
also call the global "help()" function right from the debuger prompt.
This will list some global helper functions from within libjvm.so
which can be used during debugging (among them "find(<address>" which
can be used to print out some information about an address which
belongs to the VM (e.g. a compiled method, an interpreter template, a
stub and s.o.)).
- the "-XX:StopInterpreterAt=<bytecodenumber>" is implemented in such
a way, that every generated Java bytecode template first of all
increments a global bytecode counter and then checks its value against
the argument of "StopInterpreterAt". If the two numbers are equal, the
global function "breakpoint()" will be called. "breakpoint()" is an
empty, global C-function defined in "src/os/linux/vm/os_linux.cpp". If
you want to stop at the execution of a certain Java bytecode, you
should first of all run your program with "-XX:+TraceBytecodes" to
determine the exact position of the bytecode you're interested in
(hopefully this won't take to long, because indeed the VM already
executes about half a million bytecodes before even arriving to your
program's "main()" method - this is all class loading and
initialization stuff). Then start the VM again with the appropriate
"StopInterpreterAt" option AND set a breakpoint for the global
"breakpoint()" function. The VM will now stop just before the
execution of the bytecode you're interested in, but it will stop in
the "breakpoint()" function. Issuing a "finish" command in gdb, will
return you to the code template you're interested in (you should be
able to verify this by looking up the current address within the file
which contains the generated interpreter that we've created in the
previous step). Notice that at this point, all you can do in gdb is
stepping at assembler level ("stepi", "nexti") because you're in
generated code now and there is no associated symbolic information for
this code ("next" and "step" won't work).
- certain, complex functionality of some bytecodes isn't handled
directly in the generated code. Instead, some helper methods
implemented in C++ in the VM are called. This is the case for example
for InterpreterRuntime::monitorenter. You can check the bytecode
generators, to see where there are calls into the runtime.
Hope this helps.
On Mon, Jan 5, 2009 at 6:32 AM, <xinweix at cse.unsw.edu.au> wrote:
> Hi Volker,
> Happy New Year.
> Sorry to bother you. Thank you for your attention.
> I found your email about Hotspot build instruction from the hotspot-dev
> maillist and your blog. I do appreciate your great help. However, I still
> can't quite understand the mechanism of the interpreter in hotspot. May I
> ask you some questions?
> 1) I used ddd, a graphic based client of gdb, to set up some breakpoints and
> stepped into the hotspot jvm. I can find how exactly the bytecode is
> executed, just like the following maillist:
> http://markmail.org/message/lu6izmxpqzzej4lr?q=interpreter+openjdk&page=14#query:interpreter%20openjdk+page:14+mid:wvzcrnvxlqlj5oxa+state:results .Do
> you have some idea about that?
> BTW, I successfully step into to breakpoint of StubRountes::call_stub while
> using another debuger: "insight". I use '-XX:+TraceBytecode -Xint' to see
> what is going in the Interpreter. However, it even generates a great
> amount of bytecodes when it is initializing and load the system class. I
> don't know when the interpreter runtime is initialized.
> 2) I tried to use some options, as '-Xint', '-XX:StopInterpreterAt=1',
> aiming at stopping at a specific bytecode when I can inspect the runtime
> datastructure. Unfortunately I failed. I don't understand why
> '-XX:StopInterpreterAt=1' doesn't work. The question is how to configure it
> correctly that I can stop where exactly I want.
> 3) My object is to get some information, especially about the lock and
> thread information when threads concurrently access a shared variant or try
> to lock before access using monitorenter. Can you give me some advise how
> and where I can start? Is it related to the
> I am looking forward to hearing from you.
> Alex Xie,
> University of New South Wales, Australia.
More information about the hotspot-dev