The Java Platform Debugger Architecture (JPDA) API included in the JDK lets you connect to a Java debug session and receive debug events. This code allows you to do the same things you would normally do with jdb or an IDE debugger. This is useful if you want to write your own debug, diagnostics or metrics tools.
Here is some sample code that will be debugged:
The plan is to monitor changes to the
NOTE: Sun JDK version 6 is used throughout.
Connecting to the VM
Different implementations provide different mechanisms for attaching to the VM via connectors. This allows users to connect by knowing the VM process ID (PID) or a TCP/IP host name and port, for example.
Here is the console output for performing the task using
on Windows XP:
X:\Debug>start /MIN cmd /C java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -cp .\bin Test X:\Debug>jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8000 Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > VM Started: No frames on the current call stack main watch Test.foo Deferring watch modification of Test.foo. It will be set after the class is loaded. main resume All threads resumed. > Set deferred watch modification of Test.foo Field (Test.foo) is 0, will be 346777565: "thread=main", Test.main(), line=37 bci=26 main exit X:\Debug>
The sequence of commands goes like this:
- Start the
Testmain class (the sample code) minimized in a new console (
start /MIN cmd /C) in debug mode (
-Xdebug). Have the VM listen on port 8000 (
address=8000). Wait for the debugger to attach before running (
- Start the debugger and attach to port 8000 (
hostname=localhost,port=8000). Note the connector (
watch Test.footo start watching the field.
resumeto tell the VM to resume.
exitto quit the debugger. Note that resume would have resumed until the field was hit again in the next iteration of the loop.
Using Java code to connect to the VM
In order to use the JPDA API,
you need to add the JDK
tools.jar to the classpath. It can
be found in the JDK
To interact with the VM, it is necessary to acquire a VirtualMachine object instance. The the same connector is used.
Code to connect to the VM:
For the sake of brevity I'm assuming that you can figure
com.sun.jdi imports yourself.
Test.foo with code
VirtualMachine has been acquired, we can use
to instruct it to notify us of events. For example, createClassPrepareRequests
can be used to instruct the VM to notify us when classes are loaded. The
is then used to process the generated events.
Code that monitors
The above code is demo code and not very robust, though note it
allows that the
Test class might be loaded before or after
the VM is resumed.
Sample output when run against the test class:
com.sun.jdi.SocketAttach old=0 new=-301449374 old=-301449374 new=913937357 ...