Guten Morgen
Nach langer Suche im Internet bin ich endlich auf eine brauchbare Einführung zum JDI hier auf tutorials.de gestoßen. Mein Ziel ist es ebenfalls, Zeile für Zeile durch ein Java Programm durchzusteppen und Informationen zu meinen Objekten auszulesen.
Nun hab ich mal den Code von Thomas fast 1zu1 adaptiert und ein bisschen rumgespielt. Dabei ist mir aufgefallen, dass durch Entfernen des Thread.sleep() Statements eine IncompatibleThreadStateException geworfen wir beim Aufruf von
Theoretisch müsste ich im Programmablauf auch warten, bis die aktuelle Anweisung in der Remote VM ausgeführt wurde und dann erst eine Zeile weiter gehen. Weiß da zufällig jemand mehr, warum ich diese Exception bekomme und wie ich dieses Problem lösen kann?
Hier mein Code:
Nach langer Suche im Internet bin ich endlich auf eine brauchbare Einführung zum JDI hier auf tutorials.de gestoßen. Mein Ziel ist es ebenfalls, Zeile für Zeile durch ein Java Programm durchzusteppen und Informationen zu meinen Objekten auszulesen.
Nun hab ich mal den Code von Thomas fast 1zu1 adaptiert und ein bisschen rumgespielt. Dabei ist mir aufgefallen, dass durch Entfernen des Thread.sleep() Statements eine IncompatibleThreadStateException geworfen wir beim Aufruf von
Code:
stackFrame = mainThread.frame(0);
Theoretisch müsste ich im Programmablauf auch warten, bis die aktuelle Anweisung in der Remote VM ausgeführt wurde und dann erst eine Zeile weiter gehen. Weiß da zufällig jemand mehr, warum ich diese Exception bekomme und wie ich dieses Problem lösen kann?
Hier mein Code:
Code:
public class VMStart {
public static void main(String[] args) {
//Check for argument count
if(args.length != 3){
System.err.println("Not enough parameter!");
System.exit(0);
}
String cwd = "", mainClass = "", vmPort = "";
cwd = args[0];
mainClass = args[1];
vmPort = args[2];
System.out.println("CWD: " + cwd);
System.out.println("MainClass: " + mainClass);
System.out.println("VM Port: " + vmPort);
//Init vm arguments and settings
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
AttachingConnector ac = vmm.attachingConnectors().get(0);
//Setting port
Map<String, Connector.Argument> env = ac.defaultArguments();
Connector.Argument port = env.get("port");
port.setValue(vmPort);
//Setting hostname
Connector.Argument hostname = env.get("hostname");
hostname.setValue("localhost");
//Attach vm to remote vm
VirtualMachine vm = null;
try {
vm = ac.attach(env);
} catch (IOException | IllegalConnectorArgumentsException e) {
//Doesn't work, stop here...
System.err.println("Can't connect to vm!");
e.printStackTrace();
System.exit(0);
}
//Create EventQueue and EventRequestManager for further event handling
EventQueue eventQueue = vm.eventQueue();
EventRequestManager mgr = vm.eventRequestManager();
//Set the vm to sleep for further operations
vm.suspend();
//Searching for our main thread reference
ThreadReference mainThread = null;
List<ThreadReference> threads = vm.allThreads();
for (ThreadReference thread : threads) {
if ("main".equals(thread.name())) {
mainThread = thread;
}
}
//Create and register MethodEntryRequest, so we can pause execution at first line of main later on
MethodEntryRequest methodEntryRequest = mgr.createMethodEntryRequest();
methodEntryRequest.addClassFilter(mainClass);
methodEntryRequest.addThreadFilter(mainThread);
methodEntryRequest.enable();
//Resume the execution of the remote vm
vm.resume();
//Resume the execution of the main thread in remote vm
mainThread.resume();
//Waiting for our needed MethodEntryEvent so execution started at first line of main method
Event event = null;
while (true) {
EventSet eventSet = null;
try {
eventSet = eventQueue.remove();
} catch (InterruptedException e) {
System.err.println("Something went wrong while waiting for MethodEntryEvent");
e.printStackTrace();
System.exit(0);
}
event = eventSet.eventIterator().next();
if (event instanceof MethodEntryEvent) {
break;
}
}
//Indicates whether there is still code execution in our remote vm
boolean codeIsExecuting = true;
//Step loop until there is no code execution
while(codeIsExecuting){
//Filter for steeping not into java api methods
final String[] noBreakpointRequests = {"java.*", "javax.*", "sun.*", "com.sun.*"};
//Creating our StepRequest for each line of code
StepRequest stepRequest = mgr.createStepRequest(mainThread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
for(String classInFilter : noBreakpointRequests){ //Apply filter
stepRequest.addClassExclusionFilter(classInFilter);
}
stepRequest.addCountFilter(1);
try{
stepRequest.enable();
}catch(IllegalThreadStateException e){
//program reached end of code, so there is no code execution anymore
codeIsExecuting = false;
System.out.println("Code execution ended...");
break;
}
//Extract data from current vm execution state
//TODO
System.out.println("TODO - extract data from current vm execution state");
//Test
StackFrame stackFrame = null;
try {
stackFrame = mainThread.frame(0);
System.out.println(stackFrame.location());
} catch (IncompatibleThreadStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Resume vm for code execution
vm.resume();
try {
Thread.sleep(10L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//StepRequest is done, remove it from event queue to prevent lock
mgr.deleteEventRequest(stepRequest);
}
//Debugging has ended, we free our remote vm
try{
vm.dispose();
}catch(VMDisconnectedException e){
}
//Print results
//TODO
System.out.println("TODO - print results...");
}
}