一、编写被测试类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。
分享到:
相关推荐
本篇文章将深入探讨如何使用Eclipse进行远程调试Java应用程序。 首先,确保你已经安装了Eclipse的最新版本,例如Ganymede(V3.4)。Ganymede引入了套接字监听连接器,使得远程调试变得更加灵活。在创建启动配置时,...
总结,调试Java中的JavaScript代码可以通过多种方式实现,包括使用JShell、JDI、JSDT插件以及模拟Node.js调试。选择哪种方法取决于你的具体需求、使用的开发工具以及项目的复杂程度。熟练掌握这些技巧,将极大地提高...
首先,Java Platform Debugger Architecture(JPDA)是一个开放的标准,它定义了如何构建调试器和被调试的Java应用程序之间的接口。JPDA由三个主要组件组成:Java Debug Interface (JDI),Java Virtual Machine Tool...
JDIVisitor JDIVisitor是一个Java库,用于使用Java调试接口(JDI)和访问者设计模式来构建自定义调试器应用程序。 它从的项目中汲取了灵感。 但是,JDIVisitor避开了jdiscript的类似脚本的设计,而改用了更具Java...
通过 JPDA,开发人员可以根据特定需求,扩展定制 Java 调试应用程序,开发出吸引开发人员使用的调试工具。 ### 丰富的 API JPDA 提供了丰富的 API,提供了许多实用的功能,例如,监控当前 Java 虚拟机的状态,设置...
JDI是Java虚拟机工具接口的一部分,提供了调试API,而JDB则是一个命令行工具,可以用来远程或本地调试Java应用。 1. **设置断点**:在源码中设置断点是调试的第一步。你可以使用IDE(如Eclipse、IntelliJ IDEA或...
本文介绍的是一种基于芯片仿真VCD波形格式的Java程序自动调试方法,该方法结合了Java开发接口(JDI)技术和Linux脚本,实现了Java程序的自动调试,并将结果保存为VCD(Value Change Dump)格式文件,以方便后续的...
"sa-jdi.jar"可能是某个特定项目或服务的组成部分,其中包含了Java调试接口(Java Debug Interface, JDI)的实现。 描述中的"git-2.19.0-64-bit"指的是Git版本控制系统的一个版本,具体为2.19.0的64位构建。Git是一...
调试工具直接使用 JDI 来实现调试功能。 4. **JDWP (Java Debug Wire Protocol)**: 定义了 JPDA Front-end 和 JPDA Back-end 之间通信信息的二进制格式。它是 Debugger 和 Target VM 之间通信的协议。 #### 四、...
JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),Java 调试线协议(JDWP),以及 Java 调试接口(JDI),本系列将会详细介绍这三个模块的内部细节、通过实例为读者揭开 JPDA 的面纱。
4. **Java调试接口**(JDI)和**Java调试工具**(jdb):用于调试Java应用程序,查找并修复代码中的问题。 5. **Java性能分析器**(JFR)和**Java Mission Control**(JMC):这些工具帮助开发者监控和分析应用程序...
在Java开发环境中,Eclipse是一款广泛使用的集成开发环境(IDE),尤其适合于Java应用程序的...在这个过程中,JPDA提供了一套完整的框架,使得开发者可以在不接触底层细节的情况下,实现高效且跨平台的Java程序调试。
总之,Java SE Development Kit 11.0.15.1 x64 Installer为Windows用户提供了一个强大的开发环境,包含了编写、编译、运行和调试Java应用程序所需的所有工具。随着版本的不断迭代,开发者可以期待更多的性能提升和新...
Windchill 远程调试是指在 Windchill 开发环境中,使用 Java 平台调试器(JPDA)来调试远程服务器上的 Java 应用程序。JPDA(Java Platform Debugger Architecture)是 Java 平台上的调试器定义的标准体系结构,它...
对于`java.pro`的专业开发者,他们可能更关注高级特性,如并发编程(`java.util.concurrent`包)、JVM内存管理、Java虚拟机调试接口(JDI)、Java数据库连接(JDBC)以及Java应用程序接口(Swing或JavaFX)等。...
通过分析这些代码,我们可以了解到如何在实际项目中使用JDI接口来实现调试功能,例如创建和管理调试会话、设置断点、查看变量值等。 7. **工具集成:** 许多流行的Java开发工具,如Eclipse、IntelliJ IDEA等,已经...
JDI是一个强大的API,可以用来远程调试Java应用,特别是在多线程环境下的调试,如压缩包中的"Java进阶:使用JDI调试多线程应用程序.docx"文档可能详细介绍了如何使用JDI来定位和解决并发问题。 JDI允许开发者在运行...
5. **JDI**:调试客户端使用的一组 Java 接口。 #### 三、JVM 调试参数详解 为了以调试模式启动 JVM,可以使用以下参数: - `-Xdebug`:启用调试支持。 - `-Xnoagent`:不使用默认的代理。 - `-Xrunjdwp:...