package de.tutorials;
import java.util.List;
import java.util.Map;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.VirtualMachineManager;
import com.sun.jdi.connect.AttachingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.event.Event;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.MethodEntryEvent;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.MethodEntryRequest;
import com.sun.jdi.request.StepRequest;
public class JTIExample {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
AttachingConnector ac = vmm.attachingConnectors().get(0);
Map<String, Connector.Argument> env = ac.defaultArguments();
Connector.Argument port = env.get("port");
port.setValue("8000");
Connector.Argument hostname = env.get("hostname");
hostname.setValue("localhost");
VirtualMachine vm = ac.attach(env);
EventQueue eventQueue = vm.eventQueue();
EventRequestManager mgr = vm.eventRequestManager();
// Wir legen die VM schlafen...
vm.suspend();
// Wir suchen unseren "Main-Thread"
ThreadReference mainThread = null;
List<ThreadReference> threads = vm.allThreads();
for (ThreadReference thread : threads) {
if ("main".equals(thread.name())) {
mainThread = thread;
}
}
// Hier registrieren wir einen MethodEntryRequest der dem JDI mitteilt,
// das wir an dem Methodeneintrittsereignis interessiert sind.
MethodEntryRequest methodEntryRequest = mgr.createMethodEntryRequest();
methodEntryRequest.addClassFilter("*DebugDummy");
methodEntryRequest.addThreadFilter(mainThread);
methodEntryRequest.enable();
// Wir lassen die VM weiterlaufen
vm.resume();
System.out.println("go");
mainThread.resume();
// wir suchen unser MethodEntryEvent im aktuellen EventSet der
// EventQueue
Event event = null;
while (true) {
EventSet eventSet = eventQueue.remove();
event = eventSet.eventIterator().next();
if (event instanceof MethodEntryEvent) {
break;
}
}
MethodEntryEvent mee = (MethodEntryEvent) event;
// Location location = mee.location();
// Wir wollen nur über die ersten 5 Anweisungen der main Methode steppen
// anschließend soll die Ausführung ganz normal weiter laufen...
for (int i = 0; i < 5; i++) {
// Wir erzeugen einen neuen StepRequest, da wir dem JDI mitteilen
// wollen,
// dass wir im Einzelschritt über die nächste Anweisung gehen
// wollen.
System.out.println("Try to step...");
StepRequest stepRequest = mgr.createStepRequest(mainThread,
StepRequest.STEP_LINE, StepRequest.STEP_OVER);
System.out.println("Visible stack variables:");
StackFrame currentStackFrame = mee.thread().frame(0);
List<LocalVariable> visibleVariables = currentStackFrame
.visibleVariables();
for (LocalVariable localVariable : visibleVariables) {
System.out.println(localVariable +" value: " + currentStackFrame.getValue(localVariable));
}
stepRequest.addClassFilter("*DebugDummy");
stepRequest.addCountFilter(1);
stepRequest.enable();
// Wir lassen die VM weiterlaufen
// Diese führt nun wie von uns angefordert die nächste Anweisung
// aus.
vm.resume();
// Anschließend warten wir ein paar Sekunden...
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Wir entfernen den Request aus der Event queue, damit wir
// in der nächsten Iteration einen neuen Request nachschieben
// können.
// Es darf nämlich immer nur ein Request per Thread gleichzeit
// laufen.
mgr.deleteEventRequest(stepRequest);
}
// Wir geben die fremde VM wieder frei... wir beenden unsere
// Debuggingsession
// -> Die Anwendung läuft wieder ganz normal weiter....
vm.dispose();
}
}