JdiDemo

HelloWorld.java

package com.my.jdi;

public class HelloWorld {
	public static void main(String[] args) throws Exception {
		int i = 0;
		while(true) {
			System.out.println(++i);
			Thread.sleep(5000);
		}
	}
}

SimpleDebugger.java

package com.my.jdi;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.sun.jdi.Bootstrap;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Location;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.StackFrame;
import com.sun.jdi.StringReference;
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.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.EventIterator;
import com.sun.jdi.event.EventQueue;
import com.sun.jdi.event.EventSet;
import com.sun.jdi.event.VMDeathEvent;
import com.sun.jdi.event.VMDisconnectEvent;
import com.sun.jdi.event.VMStartEvent;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;

/**
 * For javadoc of JDI, please see:
 * @see http://docs.oracle.com/javase/8/docs/jdk/api/jpda/jdi/index.html
 * @see https://www.ibm.com/developerworks/cn/java/j-lo-jpda4/index.html
 */
public class SimpleDebugger {
	private static final int BREAK_POINT_LINE = 6;
	private static final String DEBUG_CLASS = "com.my.jdi.HelloWorld";
	private static EventRequestManager eventRequestManager = null;
	private static EventSet eventSet = null;
	private static boolean vmExit = false;
	
	public static void main(String[] args) throws Exception {
		VirtualMachine targetVM = launchVM();
		
		// Get process which run target VM
		Process process = targetVM.process();
		
		registerVMEvent(targetVM);
		//classPrepareRequest.setEnabled(true);
		
		// Enter event loop 
		eventLoop(targetVM);
	 
		process.destroy();
	}

	/**
	 * Register ClassPrepareRequest
	 */
	private static void registerVMEvent(VirtualMachine targetVM) {
		eventRequestManager = targetVM.eventRequestManager();
		ClassPrepareRequest classPrepareRequest = eventRequestManager.createClassPrepareRequest();
		classPrepareRequest.addClassFilter(DEBUG_CLASS);
		classPrepareRequest.addCountFilter(1);
		classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
		// Event created by eventRequestManager is non-active, need to call enable method
		classPrepareRequest.enable();
	}

	private static void eventLoop(VirtualMachine targetVM) throws Exception {
		// EventQueue manages event from debugger for target VM
		EventQueue eventQueue = targetVM.eventQueue();
		while (!vmExit) {
			// Waits until the next available event comes.
			eventSet = eventQueue.remove();
			EventIterator eventIterator = eventSet.eventIterator();
			while (eventIterator.hasNext()) {
				Event event = (Event) eventIterator.next();
				execute(event);
			}
		}
	}
	
	private static void execute(Event event) throws Exception {
		if (event instanceof VMDisconnectEvent) {
			System.out.println("VM disconnect");
			vmExit = true;
		} else {
			if (event instanceof VMStartEvent) {
				System.out.println("VM started");
			} else if (event instanceof VMDeathEvent) {
				System.out.println("VM death");
			} else if (event instanceof ClassPrepareEvent) {
				ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) event;
				String className = classPrepareEvent.referenceType().name();
				if (DEBUG_CLASS.equals(className)) {
					System.out.println("Class " + DEBUG_CLASS + " is already prepared");
				}
				if (true) {
					// Get location
					ReferenceType referenceType = classPrepareEvent.referenceType();
					List<Location> locations = referenceType.locationsOfLine(BREAK_POINT_LINE);
					Location location = locations.get(0);
		 
					// Create BreakpointEvent
					BreakpointRequest breakpointRequest = eventRequestManager.createBreakpointRequest(location);
					breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
					breakpointRequest.enable();
				}
			} else if (event instanceof BreakpointEvent) {
				System.out.println("Reach line 10 of " + DEBUG_CLASS);
				BreakpointEvent breakpointEvent = (BreakpointEvent) event;
				ThreadReference threadReference = breakpointEvent.thread();
				StackFrame stackFrame = threadReference.frame(0);
				LocalVariable localVariable = stackFrame.visibleVariableByName("str");
				Value value = stackFrame.getValue(localVariable);
				
				String str = ((StringReference) value).value();
				System.out.println("The local variable str at line 10 is " + str + " of " + value.type().name());
			} 
			// Unless resume is being handled in another way, each EventSet should invoke EventSet.resume().
			eventSet.resume();
		}
	}
	
	/**
	 * Launch the target VM.
	 */
	private static VirtualMachine launchVM() {
		VirtualMachineManager vmManager = Bootstrap.virtualMachineManager();
		// Get all launch connectors
		List<LaunchingConnector> list = vmManager.launchingConnectors();
		for (LaunchingConnector conn: list) {
			System.out.println("LaunchingConnector: " + conn.name());
		}
		
		// Get arguments of the default launching connector
		LaunchingConnector launchingConnector = vmManager.defaultConnector();
		Map<String, Connector.Argument> env = launchingConnector.defaultArguments();
		env.get("main").setValue(DEBUG_CLASS);// Set class of main method
		env.get("suspend").setValue("true");
		
		Set<String> keySet = env.keySet();
		for (String key: keySet) {
			System.out.println("Argument: " + env.get(key));
		}
		
		// Launch target VM
		try {
			VirtualMachine vm = launchingConnector.launch(env);
			if (vm == null) {
				System.out.println("Launch failed, vm is null");
				throw new Error("Launch VM failed!");
			} else {
				System.out.println("Launch success!");
				return vm;
			}
		} catch (IOException exc) {
			throw new Error("Unable to launch target VM: " + exc);
		} catch (IllegalConnectorArgumentsException exc) {
			throw new Error("Illegal connector argument to launch target VM: " + exc);
		} catch (VMStartException exc) {
			throw new Error("Target VM failed to initialize: " + exc.getMessage());
		}
	}
}

 

转载于:https://my.oschina.net/itblog/blog/1491151

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值