0

I am writing a debugger for a Java application using JDI.

I run the debugee process using:

'/usr/lib/jvm/jdk-8-oracle-x64/bin/java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -cp (...) program.entrypoint.Test'

It's a very simple program. All it does is instantiates a Test object and sets a foo field to 0..10 in a for-loop.

Now the debugger program I got off this site: link

public class FieldMonitor {

    public static void main(String[] args) throws IOException, InterruptedException {
        // connect
        VirtualMachine vm = new VMProvider().connect(8000);

        vm.resume();

        EventQueue eventQueue = vm.eventQueue();
        while (true) {
            EventSet eventSet = eventQueue.remove();
            for (Event event : eventSet) {
                try {
                    System.out.println(event);

                    if (event instanceof VMDeathEvent || event instanceof VMDisconnectEvent) {
                        return;
                    }
                    else if(...)
                }
                catch(VMDisconnectedException e) {
                    e.printStackTrace();
                }
            }
            eventSet.resume();
        }
    }
}

Normally, I listen on more events such as hit breakpoints etc, but even a normal program execution should print me at least:

VMStartEvent in thread main
VMDeathEvent

However, randomly I will get an exception thrown, VMDisconnectedException, when I try to print the event. Then I will get:

com.sun.jdi.VMDisconnectedException
    at com.sun.tools.jdi.TargetVM.waitForReply(TargetVM.java:304)
    at com.sun.tools.jdi.VirtualMachineImpl.waitForTargetReply(VirtualMachineImpl.java:1036)
    at com.sun.tools.jdi.PacketStream.waitForReply(PacketStream.java:69)
    at com.sun.tools.jdi.JDWP$ThreadReference$Name.waitForReply(JDWP.java:4931)
    at com.sun.tools.jdi.JDWP$ThreadReference$Name.process(JDWP.java:4912)
    at com.sun.tools.jdi.ThreadReferenceImpl.name(ThreadReferenceImpl.java:168)
    at com.sun.tools.jdi.EventSetImpl$ThreadedEventImpl.toString(EventSetImpl.java:184)
    at java.lang.String.valueOf(String.java:2981)
    at java.io.PrintStream.println(PrintStream.java:821)
    at virtualmachine.FieldMonitor.main(FieldMonitor.java:33)
VMDeathEvent

My VMStartEvent (or any other if I listen to more events) now houses an exception. When I put a breakpoint in the catch-clause, I get:

com.sun.jdi.VMDisconnectedException: connection is closed

After this exception, I still get a VMDeathEvent from the set. Now, I have no idea why that happens randomly, and why it happens at all, since my debugee process is started as suspended and I only resume it after I attached myself as the debugger.

oskarm
  • 123
  • 3
  • 8

2 Answers2

0

First of all, would need more information on what exactly you are doing with events. Here's my output of similar program:

VMStartEvent in thread main
VMDeathEvent
VMDisconnectEvent

However, I don't have the statement:

vm.resume();

In case I include it, I get the same exception.

Exception in thread "main" com.sun.jdi.VMDisconnectedException: connection is closed
    at com.sun.tools.jdi.TargetVM.send(TargetVM.java:274)
    at com.sun.tools.jdi.VirtualMachineImpl.sendToTarget(VirtualMachineImpl.java:1011)
    at com.sun.tools.jdi.PacketStream.send(PacketStream.java:41)
    at com.sun.tools.jdi.JDWP$ThreadReference$Name.enqueueCommand(JDWP.java:4928)
    at com.sun.tools.jdi.JDWP$ThreadReference$Name.process(JDWP.java:4914)
    at com.sun.tools.jdi.ThreadReferenceImpl.name(ThreadReferenceImpl.java:77)
    at com.sun.tools.jdi.EventSetImpl$ThreadedEventImpl.toString(EventSetImpl.java:168)
    at java.lang.String.valueOf(String.java:2826)
    at java.io.PrintStream.println(PrintStream.java:771)

So, I guess it has to do with vm.resume() function call that is causing problem. Hope, that helps.

devilpreet
  • 749
  • 4
  • 18
0

The exception is thrown by event.toString occuring inside System.out.println(event). It can happen if the event is an instance of ThreadedEventImpl:

public String toString() {
    return eventName() + " in thread " + thread.name();
}

Because thread.name() sends a command to the VM and wait for the reply but the VM may be already disconnected.

Adrien Piquerez
  • 1,009
  • 10
  • 11