Reputation: 329
I have two class. One is debuggee and another one is debugger. I use debugger to debug debuggee. Here's my code:
JDIExampleDebuggee
package com.linuxea;
public class JDIExampleDebuggee {
public static void main(String[] args) {
String jpda = "Java Platform Debugger Architecture";
System.out.println("Hi Everyone, Welcome to " + jpda); // add a break point here
String jdi = "Java Debug Interface"; // add a break point here and also stepping in here
String text = "Today, we'll dive into " + jdi;
System.out.println(text);
}
}
JDIExampleDebugger
package com.linuxea;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.ClassType;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Location;
import com.sun.jdi.StackFrame;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.Connector.Argument;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.event.BreakpointEvent;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.LocatableEvent;
import com.sun.jdi.event.StepEvent;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.StepRequest;
import java.util.Map;
public class JDIExampleDebugger<T> {
private Class<T> debugClass;
private int[] breakPointLines;
public static void main(String[] args) {
JDIExampleDebugger<JDIExampleDebuggee> debuggerInstance = new JDIExampleDebugger<>();
debuggerInstance.debugClass = JDIExampleDebuggee.class;
debuggerInstance.breakPointLines = new int[]{6};
VirtualMachine vm;
try {
vm = debuggerInstance.connectAndLaunchVM();
debuggerInstance.enableClassPrepareRequest(vm);
EventSet eventSet;
while ((eventSet = vm.eventQueue().remove()) != null) {
for (Event event : eventSet) {
System.out.println(event.getClass().getName());
if (event instanceof ClassPrepareEvent) {
debuggerInstance.setBreakPoints(vm, (ClassPrepareEvent) event);
}
if (event instanceof BreakpointEvent) {
debuggerInstance.displayVariables((BreakpointEvent) event);
}
if (event instanceof BreakpointEvent) {
debuggerInstance.enableStepRequest(vm, (BreakpointEvent) event);
}
if (event instanceof StepEvent) {
debuggerInstance.displayVariables((StepEvent) event);
}
vm.resume();
}
}
} catch (VMDisconnectedException e) {
System.out.println("Virtual Machine is disconnected.");
throw new RuntimeException(e);
} catch (Exception e) {
e.printStackTrace();
}
}
public void enableStepRequest(VirtualMachine vm, BreakpointEvent event) {
// enable step request for last break point
if (event.location().toString().
contains(debugClass.getName() + ":" + breakPointLines[breakPointLines.length - 1])) {
StepRequest stepRequest = vm.eventRequestManager()
.createStepRequest(event.thread(), StepRequest.STEP_LINE, StepRequest.STEP_OVER);
stepRequest.enable();
}
}
public VirtualMachine connectAndLaunchVM() throws Exception {
LaunchingConnector launchingConnector = Bootstrap.virtualMachineManager()
.defaultConnector();
Map<String, Argument> arguments = launchingConnector.defaultArguments();
arguments.get("main").setValue(debugClass.getName());
return launchingConnector.launch(arguments);
}
public void enableClassPrepareRequest(VirtualMachine vm) {
ClassPrepareRequest classPrepareRequest = vm.eventRequestManager().createClassPrepareRequest();
classPrepareRequest.addClassFilter(debugClass.getName());
classPrepareRequest.enable();
}
public void setBreakPoints(VirtualMachine vm, ClassPrepareEvent event)
throws AbsentInformationException {
ClassType classType = (ClassType) event.referenceType();
for (int lineNumber : breakPointLines) {
Location location = classType.locationsOfLine(lineNumber).get(0);
BreakpointRequest bpReq = vm.eventRequestManager().createBreakpointRequest(location);
bpReq.enable();
}
}
public void displayVariables(LocatableEvent event) throws IncompatibleThreadStateException,
AbsentInformationException {
StackFrame stackFrame = event.thread().frame(0);
if (stackFrame.location().toString().contains(debugClass.getName())) {
Map<LocalVariable, Value> visibleVariables = stackFrame
.getValues(stackFrame.visibleVariables());
System.out.println("Variables at " + stackFrame.location().toString() + " > ");
for (Map.Entry<LocalVariable, Value> entry : visibleVariables.entrySet()) {
System.out.println(entry.getKey().name() + " = " + entry.getValue());
}
}
}
}
This is output:
com.sun.tools.jdi.EventSetImpl$VMStartEventImpl
com.sun.tools.jdi.EventSetImpl$VMDeathEventImpl
com.sun.tools.jdi.EventSetImpl$VMDisconnectEventImpl
Virtual Machine is disconnected.
Exception in thread "main" java.lang.RuntimeException: com.sun.jdi.VMDisconnectedException
at com.linuxea.JDIExampleDebugger.main(JDIExampleDebugger.java:64)
Caused by: com.sun.jdi.VMDisconnectedException
at com.sun.tools.jdi.EventQueueImpl.removeUnfiltered(EventQueueImpl.java:199)
at com.sun.tools.jdi.EventQueueImpl.remove(EventQueueImpl.java:96)
at com.sun.tools.jdi.EventQueueImpl.remove(EventQueueImpl.java:82)
at com.linuxea.JDIExampleDebugger.main(JDIExampleDebugger.java:41)
Process finished with exit code 1
As you can see there is nothing useful event. The target VM is start but stop immediately.
I want to learn JDI using this tutorial. The code is learn from java-debug-interface.
I try many times but could not find out anything wrong.
The tutorial looks simple.
Upvotes: 0
Views: 237
Reputation: 329
Thanks god!I google and find a resolution from https://itsallbinary.com/java-debug-interface-api-jdi-hello-world-example-programmatic-debugging-for-beginners/
Upvotes: 0