172 lines
6.3 KiB
Java
172 lines
6.3 KiB
Java
|
package com.baeldung.jdi;
|
||
|
|
||
|
import java.io.IOException;
|
||
|
import java.io.InputStreamReader;
|
||
|
import java.io.OutputStreamWriter;
|
||
|
import java.util.Map;
|
||
|
|
||
|
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;
|
||
|
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
|
||
|
import com.sun.jdi.connect.LaunchingConnector;
|
||
|
import com.sun.jdi.connect.VMStartException;
|
||
|
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;
|
||
|
|
||
|
public class JDIExampleDebugger {
|
||
|
|
||
|
private Class debugClass;
|
||
|
private int[] breakPointLines;
|
||
|
|
||
|
public Class getDebugClass() {
|
||
|
return debugClass;
|
||
|
}
|
||
|
|
||
|
public void setDebugClass(Class debugClass) {
|
||
|
this.debugClass = debugClass;
|
||
|
}
|
||
|
|
||
|
public int[] getBreakPointLines() {
|
||
|
return breakPointLines;
|
||
|
}
|
||
|
|
||
|
public void setBreakPointLines(int[] breakPointLines) {
|
||
|
this.breakPointLines = breakPointLines;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the debug class as the main argument in the connector and launches the VM
|
||
|
* @return VirtualMachine
|
||
|
* @throws IOException
|
||
|
* @throws IllegalConnectorArgumentsException
|
||
|
* @throws VMStartException
|
||
|
*/
|
||
|
public VirtualMachine connectAndLaunchVM() throws IOException, IllegalConnectorArgumentsException, VMStartException {
|
||
|
LaunchingConnector launchingConnector = Bootstrap.virtualMachineManager().defaultConnector();
|
||
|
Map<String, Connector.Argument> arguments = launchingConnector.defaultArguments();
|
||
|
arguments.get("main").setValue(debugClass.getName());
|
||
|
VirtualMachine vm = launchingConnector.launch(arguments);
|
||
|
return vm;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates a request to prepare the debug class, add filter as the debug class and enables it
|
||
|
* @param vm
|
||
|
*/
|
||
|
public void enableClassPrepareRequest(VirtualMachine vm) {
|
||
|
ClassPrepareRequest classPrepareRequest = vm.eventRequestManager().createClassPrepareRequest();
|
||
|
classPrepareRequest.addClassFilter(debugClass.getName());
|
||
|
classPrepareRequest.enable();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the break points at the line numbers mentioned in breakPointLines array
|
||
|
* @param vm
|
||
|
* @param event
|
||
|
* @throws AbsentInformationException
|
||
|
*/
|
||
|
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();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Displays the visible variables
|
||
|
* @param event
|
||
|
* @throws IncompatibleThreadStateException
|
||
|
* @throws AbsentInformationException
|
||
|
*/
|
||
|
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());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Enables step request for a break point
|
||
|
* @param vm
|
||
|
* @param event
|
||
|
*/
|
||
|
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 static void main(String[] args) throws Exception {
|
||
|
|
||
|
JDIExampleDebugger debuggerInstance = new JDIExampleDebugger();
|
||
|
debuggerInstance.setDebugClass(JDIExampleDebuggee.class);
|
||
|
int[] breakPoints = {6, 9};
|
||
|
debuggerInstance.setBreakPointLines(breakPoints);
|
||
|
VirtualMachine vm = null;
|
||
|
|
||
|
try {
|
||
|
vm = debuggerInstance.connectAndLaunchVM();
|
||
|
debuggerInstance.enableClassPrepareRequest(vm);
|
||
|
|
||
|
EventSet eventSet = null;
|
||
|
while ((eventSet = vm.eventQueue().remove()) != null) {
|
||
|
for (Event event : eventSet) {
|
||
|
if (event instanceof ClassPrepareEvent) {
|
||
|
debuggerInstance.setBreakPoints(vm, (ClassPrepareEvent)event);
|
||
|
}
|
||
|
|
||
|
if (event instanceof BreakpointEvent) {
|
||
|
event.request().disable();
|
||
|
debuggerInstance.displayVariables((BreakpointEvent) event);
|
||
|
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.");
|
||
|
} catch (Exception e) {
|
||
|
e.printStackTrace();
|
||
|
}
|
||
|
finally {
|
||
|
InputStreamReader reader = new InputStreamReader(vm.process().getInputStream());
|
||
|
OutputStreamWriter writer = new OutputStreamWriter(System.out);
|
||
|
char[] buf = new char[512];
|
||
|
|
||
|
reader.read(buf);
|
||
|
writer.write(buf);
|
||
|
writer.flush();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|