Using JDWP and JVMTI to obtain information of the running Java application

2.8k views Asked by At

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. 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?

1

There are 1 answers

3
h3xStream On

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

  • Tracing method call and return (possibly for doing profiling or logging)
  • Field value changes
  • VM information (see name() and description() in the example)
  • Evaluate expression to execute arbitrary code