Using JDWP and JVMTI to obtain information of the running Java application
We are developing an application for obtaining the information of a running java application using JDWP and JVMTI. Sun Java comes with a reference implementation of JDWP so using agentlib -jdwp: will use the reference implementation. Our aim is to study JVMTI and write JVMTI agents to get specific detail. Also creating a Front end using which the user can request for specific information about the running java application. For this we would have to write our implementation for JDWP开发者_StackOverflow中文版. Though we were able to write JVMTI agents and use it to attach to the java application from the command line. But our aim is to send this information to another java process (Front End).
So we have a Java application- Front end querying for information from the JVMTI Agents (Back-End). These agents should be able to attach to the running java application we are going to inspect dynamically. Any ideas on how this can be done? Or has anyone tried this before?
The JDK has a built-in Java api for remote/local debug (com.sun.jdi.).
To quickly start using the api, you can look at examples in $JDK_DIR\demo\jpda\examples.jar. [More details]
Since the official examples are not so clear, here is reusable example (inspired by this blog post):
VMAcquirer.java (Connection manager)
public class VMAcquirer {
public VirtualMachine connect(String host,int port) throws IOException {
String strPort = Integer.toString(port);
AttachingConnector connector = getConnector();
try {
VirtualMachine vm = connect(connector,host, strPort);
return vm;
} catch (IllegalConnectorArgumentsException e) {
throw new IllegalStateException(e);
}
}
private AttachingConnector getConnector() {
VirtualMachineManager vmManager = Bootstrap.virtualMachineManager();
for (Connector connector : vmManager.attachingConnectors()) {
if("com.sun.jdi.SocketAttach".equals(connector.name()))
return (AttachingConnector) connector;
}
throw new IllegalStateException();
}
private VirtualMachine connect(AttachingConnector connector,String host,String port)
throws IllegalConnectorArgumentsException, IOException {
Map<String, Connector.Argument> args = connector.defaultArguments();
Connector.Argument portArg = args.get("port");
portArg.setValue(port);
Connector.Argument addressArg = args.get("hostname");
addressArg.setValue(host);
return connector.attach(args);
}
}
Monitor.java (Actual monitoring)
class Monitor {
public static void main(String[] args){
VirtualMachine vm = new VMAcquirer().connect("192.168.0.x", 2600);
System.out.println("name="+vm.name()); //Info about the remote VM
System.out.println("description="+vm.description());
EventRequestManager erm = vm.eventRequestManager();
[...] //Send request using erm instance
loopEventQueue(vm); //Start a loop to listen to the events received
}
public static void loopEventQueue(VirtualMachine vm) throws InterruptedException {
EventQueue eventQueue = vm.eventQueue();
while (true) {
EventSet eventSet = eventQueue.remove();
for (Event ev : eventSet) {
if(ev instanceof MethodEntryEvent) {
handleMethodEntryEvent(ev);
}
[...]
}
}
}
}
Required by the application being monitor
java -Xdebug -Xrunjdwp:transport=dt_socket,address=2600,server=y,suspend=n ...
Informations available through JDWP
精彩评论