/**
*
*/
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.ObjectReference;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
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;
/**
* @author Thomas.Darimont
*
*/
public class Debugger {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
VirtualMachine vm = connectToJVM("localhost", 8000);
EventQueue eventQueue = vm.eventQueue();
EventRequestManager mgr = vm.eventRequestManager();
// Wir legen die VM schlafen...
vm.suspend();
// Wir suchen unseren "Main-Thread"
ThreadReference mainThread = findMainThread(vm);
String classFilter = "*Main";
// Hier registrieren wir einen MethodEntryRequest der dem JDI mitteilt,
// das wir an dem Methodeneintrittsereignis interessiert sind.
MethodEntryRequest methodEntryRequest = mgr.createMethodEntryRequest();
methodEntryRequest.addClassFilter(classFilter);
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 < 3; i++) {
doSingleStep(vm, mgr, mainThread, classFilter, 1000L);
}
System.out.println(mainThread.frameCount());
StackFrame stackFrame = mainThread.frame(0);
LocalVariable localVariableClazz = stackFrame
.visibleVariableByName("clazz");
Value localVariableClazzValue = stackFrame.getValue(localVariableClazz);
ObjectReference objectReference = (ObjectReference) localVariableClazzValue;
List<ObjectReference> objectReferences = objectReference
.referringObjects(Long.MAX_VALUE);
for (ObjectReference o : objectReferences) {
System.out.println(o);
}
vm.dispose();
}
/**
* @param vm
* @param mgr
* @param mainThread
* @param classFilter
*/
private static void doSingleStep(VirtualMachine vm,
EventRequestManager mgr, ThreadReference mainThread,
String classFilter, long someSleepTime) {
// 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);
stepRequest.addClassFilter(classFilter);
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(someSleepTime);
} 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);
}
private static VirtualMachine connectToJVM(String hostname, int port)
throws Exception {
VirtualMachineManager virtualMachineManager = Bootstrap
.virtualMachineManager();
AttachingConnector attachingConnector = (AttachingConnector) virtualMachineManager
.attachingConnectors().get(0);
Map<String, Connector.Argument> env = attachingConnector
.defaultArguments();
Connector.Argument portArgument = env.get("port");
portArgument.setValue(port + "");
Connector.Argument hostnameArgument = env.get("hostname");
hostnameArgument.setValue(hostname);
return attachingConnector.attach(env);
}
/**
* @param vm
* @param mainThread
* @return
*/
private static ThreadReference findMainThread(VirtualMachine vm) {
List<ThreadReference> threads = vm.allThreads();
for (ThreadReference thread : threads) {
if ("main".equals(thread.name())) {
return thread;
}
}
throw new RuntimeException("Main Thread not found!");
}
}