I would like to set a breakpoint in an application before it starts to run, so that I can make sure the application does not pass the breakpoint on startup.
In order to set a breakpoint you need to do something like:
EventRequestManager reqMan = vm.eventRequestManager();
BreakpointRequest bpReq = reqMan.createBreakpointRequest(locationForBreakpoint);
bpReq.enable();
In order to get the Location for the breakpoint, you can do something like:
Method method = location.method();
List<Location> locations = method.locationsOfLine(55);
Location locationForBreakpoint = locations.get(0);
In order to get a Method you can do something like:
classType.concreteMethodByName(methodNname, String signature)
However in order to get that classType you seem to require an ObjectReference which seems to require a running JVM.
Is there any way to set the breakpoint before the application JVM runs, to be sure the breakpoint is not passed during application startup?
First of all start you target program using a LaunchingConnector to get back the target virtual machine.
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
LaunchingConnector lc = vmm.launchingConnectors().get(0);
// Equivalently, can call:
// LaunchingConnector lc = vmm.defaultConnector();
Map<String, Connector.Argument> env = lc.defaultArguments();
env.get("main").setValue("p.DebugDummy");
env.get("suspend").setValue("true");
env.get("home").setValue("C:/Program Files/Java/jdk1.7.0_51");
VirtualMachine vm = lc.launch(env);
(change environment values according to your needs,but remember to start target VM with suspended=true
).
With this VM in you hand intercept a ClassPrepareEvent using a ClassPrepareRequest.
ClassPrepareRequest r = reqMan.createClassPrepareRequest();
r.addClassFilter("myclasses.SampleClass");
r.enable();
Create a ClassPrepareEvent
handler
executor.execute(()-> {
try {
while(true)
{
EventQueue eventQueue = vm.eventQueue();
EventSet eventSet = eventQueue.remove();
EventIterator eventIterator = eventSet.eventIterator();
if (eventIterator.hasNext()) {
Event event = eventIterator.next();
if(event instanceof ClassPrepareEvent) {
ClassPrepareEvent evt = (ClassPrepareEvent) event;
ClassType classType = (ClassType) evt.referenceType();
List<Location> locations = referenceType.locationsOfLine(55);
Location locationForBreakpoint = locations.get(0);
vm.resume();
}
}
}
} catch (InterruptedException | AbsentInformationException | IncompatibleThreadStateException e) {
e.printStackTrace();
}
}
then resume target VM with a call to vm.resume() to run program. I hope this solve your problem.
来源:https://stackoverflow.com/questions/35420987/how-do-you-set-a-breakpoint-before-executing