简体   繁体   中英

How to access JVM internal data structures using the Hotspot Dynamic Attach Mechanism?

According to the OpenJDK's website , it is possible to attach a thread to Hotspot (Dynamic Attach API) which can collect information about it. I couldn't find any material on the internet on how to obtain information about Hotspot's internal data structures such as the operand stack or the state of the bytecode interpreter(to know which bytecode is currently executing) or to retrieve the current Stack Frame etc.

Also, if this is not possible with the Dynamic Attach API, how can this be done using the Serviceability Agent? The only example I found on the internet is this gist from Github which shows how to attach to a running JVM and get the values of some fields. But how to access the aformentioned internal data structures in the JVM?

The article Creating Your Own Debugging Tools briefly describes both Dynamic Attach and Serviceability Agent.

Dynamic Attach allows to connect to a running JVM and execute one of the predefined commands like

  • Print stack traces
  • Dump heap
  • Query or set a VM flag
  • Load an agent library
  • etc.

Basically, standard jstack , jmap and jcmd tools cover nearly all functions provided by Dynamic Attach. This API is not for accessing internal JVM structures. I doubt it can help with your task, except for loading a custom JVM TI library.


Serviceability Agent is closer to the JVM internal structures. Indeed, it can read JVM memory and recover structures like Code Cache, Stack Frames, TLAB, Constant Pool etc.

SA javadoc is available here . There are some examples of SA-based tools in JDK sources.

However, SA does not meet your requirements either.

  1. It is a read only interface.
  2. It works out of the process. SA-based tools suspend the JVM process entirely and read its memory using ptrace .
  3. It is rather slow. It's main purpose is to debug unresponsive (or dead) JVM process.

Regarding operand stack, bytecode pointer etc. These notions exist only in the interpreter. Once a method is JIT-compiled, it no longer has structures you are asking about.

  • The locals and operands may be allocated in CPU registers or converted to constants.
  • The machine code does not always map one-to-one to the bytecode.
  • An inlined method may not even have its own stack frame, and so on.

Executing bytecodes one by one would mean giving up JIT compilation. JVM TI SingleStep indeed works only in the interpreter. Java application may work 10-100 times slower in a purely interpreted mode.

If you want to keep performance of your debugger reasonable, processing each bytecode instruction one after another is not an option. As told before, instrumentation is the right way to go. Note that it's not necessary to intercept every single bytecode - instrumenting basic blocks should be enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM