Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java agent with jvmti load at runtime, unload from within

I'm writing a Java agent to interact with JVMTI. For reasons I won't get into, I need to use JVMTI (the C interface inside the java process) rather than the Java APIs like java.lang.instrument or JDI. I would like to be able to do a couple of things which appear not to be supported directly.

  1. Is there a way to load an agent after the Java process has already started?
  2. Is there a way to unload a Java agent (short of killing the whole Java process) either from inside the JVMTI code or from outside the process? For instance, could I safely call dlclose() from the JVMTI code if I can find the handle for the dynamically-loaded module?

If these operations can't be done, is there a way to pass data to a Java agent after it's loaded? Is there a normal way to do this through some Java command-line utility? If not, can I safely create a thread and have it listen to a socket using the standard C or C++ library calls within the code for my agent?

If it helps, don't worry about supporting Windows with your answer - I'm undertaking this project to extend a Unix-only debugging tool.

Note: I've already seen this but thought there might be some normal way to do it that isn't in the JVMTI standard.

like image 599
Dan Avatar asked Jun 29 '13 05:06

Dan


1 Answers

  1. You can only inject (deploy) an agent either at start time of the JVM by passing the argument -agentlib:<agent-lib-name>=<options> or -agentpath:<path-to-agent>=<options>.

    The other way is through Java itself. This depends heavily on the JVM, for that reason it is out of JVMTI specification scope. For instance if there is the VirtualMachine class through the method loadAgentPath(agentPath, options). If you want to execute this from within the native JVMTI code you would need to do Bytecode instrumentation.

  2. I am not sure, similar to 1. you could run the Java unload method through Bytecode instrumentation. If dlclose() works I do not see a problem in doing that.

As you see, you can pass data to the Java agent by using the options. Alternatively, if you want to pass data continuously between both instances you can open two sockets and write/read between them. I used Protobuf

like image 106
Konrad Reiche Avatar answered Sep 28 '22 09:09

Konrad Reiche