使用JDI接口调试Java程序

一、编写被测试类Test.java。每隔5秒钟运行一次printHello()方法打印一次信息。

package test;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class Test {

public static void main(String[] args) {
new Thread() {

@Override
public void run() {
Test test = new Test();
while (true) {
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
printHello();
}
}
}.start();
}

protected static void printHello() {
Random r = new Random();
int i = r.nextInt();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(new Date());

System.out.println(date + " : " + i);
}

}



二、编写调试类TestDebugger.java。用来远程调试Test.java。该方法在test.Test方法第34行设置断点,并监听。当程序运行到34行时,获取堆栈中变量信息,打印出来。

package test;

import java.util.List;
import java.util.Map;

import com.sun.jdi.Bootstrap;
import com.sun.jdi.IntegerValue;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Location;
import com.sun.jdi.Method;
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.AttachingConnector;
import com.sun.jdi.connect.Connector;
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.MethodEntryEvent;
import com.sun.jdi.event.VMDisconnectEvent;
import com.sun.jdi.event.VMStartEvent;
import com.sun.jdi.request.BreakpointRequest;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.tools.jdi.SocketAttachingConnector;

public class TestDebugger {

public static final String HOST = "hostname";

public static final String PORT = "port";

static VirtualMachine vm;

static EventQueue eventQueue;

static EventRequestManager eventRequestManager;

static Process process;

static EventSet eventSet;

static boolean vmExit = false;

public static void main(String[] args) throws Exception {

// 一、取得连接器
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
List<AttachingConnector> connectors = vmm.attachingConnectors();
SocketAttachingConnector sac = null;
for (AttachingConnector ac : connectors) {
if (ac instanceof SocketAttachingConnector) {
sac = (SocketAttachingConnector) ac;
break;
}
}
if (sac == null) {
System.out.println("JDI error");
return;
}

// 二、连接到远程虚拟器
Map<String, Connector.Argument> arguments = sac.defaultArguments();
Connector.Argument hostArg = (Connector.Argument) arguments.get(HOST);
Connector.Argument portArg = (Connector.Argument) arguments.get(PORT);

// hostArg.setValue("127.0.0.1");
portArg.setValue(String.valueOf(8800));

vm = sac.attach(arguments);
process = vm.process();
eventRequestManager = vm.eventRequestManager();

// 三、取得要关注的类和方法
List<ReferenceType> classesByName = vm.classesByName("test.Test");
if (classesByName == null || classesByName.size() == 0) {
System.out.println("No class found");
return;
}
ReferenceType rt = classesByName.get(0);
List<Method> methodsByName = rt.methodsByName("printHello");
if (methodsByName == null || methodsByName.size() == 0) {
System.out.println("No method found");
return;
}
Method method = methodsByName.get(0);

// 四、注册监听
vm.setDebugTraceMode(VirtualMachine.TRACE_EVENTS);
vm.resume();

List<Location> locations = classesByName.get(0).locationsOfLine(34);
BreakpointRequest breakpointRequest = eventRequestManager.createBreakpointRequest(locations.get(0));
breakpointRequest.enable();

// MethodEntryRequest methodEntryRequest = eventRequestManager.createMethodEntryRequest();
// methodEntryRequest.addClassFilter(rt);
// methodEntryRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
// // methodEntryRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
//
// methodEntryRequest.enable();
//
// BreakpointRequest breakpointRequest = eventRequestManager.createBreakpointRequest(method.location());
// breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
// // breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
// breakpointRequest.enable();

// ClassPrepareRequest classPrepareRequest = eventRequestManager.createClassPrepareRequest();
// classPrepareRequest.addClassFilter("test.Test");
// classPrepareRequest.addCountFilter(1);
// classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
// classPrepareRequest.enable();

eventLoop();

}

private static void eventLoop() throws Exception {
eventQueue = vm.eventQueue();
while (true) {
if (vmExit == true) {
break;
}
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 VMStartEvent) {
System.out.println("VM started");
eventSet.resume();
} else if (event instanceof BreakpointEvent) {
System.out.println("Reach Method printHello of test.Test");

BreakpointEvent breakpointEvent = (BreakpointEvent) event;
ThreadReference threadReference = breakpointEvent.thread();
StackFrame stackFrame = threadReference.frame(0);

stackFrame.visibleVariables();

// 获取date变量
LocalVariable localVariable = stackFrame.visibleVariableByName("date");
Value value = stackFrame.getValue(localVariable);
String date = ((StringReference) value).value();

LocalVariable localVariable1 = stackFrame.visibleVariableByName("i");
Value value1 = stackFrame.getValue(localVariable1);
int i = ((IntegerValue) value1).intValue();

System.out.println("Debugger print[" + date + " : " + i + "]");

eventSet.resume();
} else if (event instanceof MethodEntryEvent) {
MethodEntryEvent mee = (MethodEntryEvent) event;
Method method = mee.method();
System.out.println(method.name() + " was Entered!");
eventSet.resume();
} else if (event instanceof VMDisconnectEvent) {
vmExit = true;
} else if (event instanceof ClassPrepareEvent) {
ClassPrepareEvent classPrepareEvent = (ClassPrepareEvent) event;
String mainClassName = classPrepareEvent.referenceType().name();
if (mainClassName.equals("test.Test")) {
System.out.println("Class " + mainClassName + " is already prepared");
}
if (true) {
// Get location
ReferenceType referenceType = classPrepareEvent.referenceType();
List locations = referenceType.locationsOfLine(34);
Location location = (Location) locations.get(0);

// Create BreakpointEvent
BreakpointRequest breakpointRequest = eventRequestManager.createBreakpointRequest(location);
breakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
breakpointRequest.enable();
}
eventSet.resume();
} else {
eventSet.resume();
}
}
}



三、运行被调试类Test.java。以Debug模式运行,监听8800端口。

D:\workspace\Jdi\bin>java -Xdebug -agentlib:jdwp=transport=dt_socket,serve
r=y,suspend=y,address=8800 -cp . test.Test


四、运行调试类TestDebugger。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值