我正在使用 JDI 为 Java 应用程序编写调试器。
我使用以下方法运行调试进程:
'/usr/lib/jvm/jdk-8-oracle-x64/bin/java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -cp (...) program.entrypoint.Test'
这是一个非常简单的程序。它所做的只是实例化一个 Test 对象并在 for 循环中将 foo 字段设置为 0..10。
现在我从这个网站下车的调试器程序: 链接
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();
}
}
}
通常,我会监听更多事件,例如命中断点等,但即使是正常的程序执行也至少应该打印我:
VMStartEvent in thread main
VMDeathEvent
但是,当我尝试打印事件时,会随机抛出异常 VMDisconnectedException。然后我会得到:
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
我的 VMStartEvent (或任何其他,如果我听更多的事件)现在包含一个异常。当我在 catch 子句中放置断点时,我得到:
com.sun.jdi.VMDisconnectedException: connection is closed
在这个异常之后,我仍然从集合中得到一个 VMDeathEvent。现在,我不知道为什么会随机发生,也不知道为什么会发生,因为我的被调试进程以挂起的方式启动,并且只有在我将自己附加为调试器后才恢复它。