1

My goal is to implement a small library in Java that would allow to programmatically take some actions and then suspend the current JVM until a debugger is connected to it.

I imagine parts of it at least are possible, for ex. when starting a JVM in debug mode with suspend=y it will wait for a debugger to connect. Does anyone have a pointer to the code that implements this functionality?

It seems that JVMTI might enable me to do something like this programmatically, but I'm wondering if there is a higher level API or if someone has code examples/explanations on how to interact with JVMTI from Java (my assumption is that the agent in JVMTI will be able to suspend the JVM but I need to call it from the Java code).

Update: Here is what I found so far.

1) It is relatively simple to invoke JVMTI code from Java by having a JNI function that would then use the jvmti env. The trick is to keep a reference to the jvmtienv during the loading of the agent. This blog post has been very helpful https://www.javacodegeeks.com/2014/12/own-your-heap-iterate-class-instances-with-jvmti.html.

2) The functionality of the suspend option that can be passed to the JVM on startup and wait for a debugger to connect before resuming execution doesn't seem to be something that can be reused. It seems that it might just be the debugger agent that listens on this port and once a connection is established it will just proceed with execution/resume threads.

3) For the higher level API to achieve what I want, it seems that the plain thread.suspend() might do what I want. The question then is how does it differ from SuspendThread. I opened this other question for that: What is the difference between JVMTI SuspendThread and Javas thread.suspend?.

eugen
  • 5,856
  • 2
  • 29
  • 26
  • After some experimentation I'm able to suspend the threads through JNI and using JVMTI. However now I suspect that the suspend functionality is something purely ad hoc that might block the current thread that runs the agent at startup and waits for the debugger to connect on the open port so it has nothing to do with thread suspending on the fly. Any ideas on how to achieve the part "wait for a debugger to connect"? – eugen Feb 09 '19 at 11:00
  • 1
    Looks like you've already found JVM TI [SuspendThread](https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#SuspendThread) and [SuspendThreadList](https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#SuspendThreadList) functions. Why don't they work for you? Using them you may suspend all threads except current, and in the current thread continue doing whatever you want, e.g. waiting for an external signal. – apangin Feb 09 '19 at 16:37
  • Oh they would work, I was just hoping that there would be some built in mechanism that allows operations to be resumed when a debugger is attached to the JVM. – eugen Feb 09 '19 at 20:24
  • 2
    Right, the debugger is just another JVM TI agent. JVM does not open ports or wait for connections - it's a job of JDWP agent. There is no public API to know if debugger is attached. However, there is a tricky way that may help, e.g. [checking "sun.jdwp.listenerAddress" agent property](https://stackoverflow.com/a/28775900/3448419). – apangin Feb 09 '19 at 22:24
  • @apangin I ended up putting together a prototype of all that. The ugly bit though is that to detect when a debugger client connects to the JVM I'm using netstat through a subprocess to find out when the connection is established on the debug port... do you know of any better solution? – eugen Feb 15 '19 at 18:16
  • 1
    "sun.jdwp.listenerAddress" property mentioned above is removed as soon as debugger client connects. It reappears again after the client disconnects. – apangin Feb 16 '19 at 00:02

0 Answers0