`
elvis4139
  • 浏览: 148293 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

使用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。

分享到:
评论

相关推荐

    使用 Eclipse 远程调试 Java 应用程序

    本篇文章将深入探讨如何使用Eclipse进行远程调试Java应用程序。 首先,确保你已经安装了Eclipse的最新版本,例如Ganymede(V3.4)。Ganymede引入了套接字监听连接器,使得远程调试变得更加灵活。在创建启动配置时,...

    java js引擎调试js代码

    总结,调试Java中的JavaScript代码可以通过多种方式实现,包括使用JShell、JDI、JSDT插件以及模拟Node.js调试。选择哪种方法取决于你的具体需求、使用的开发工具以及项目的复杂程度。熟练掌握这些技巧,将极大地提高...

    Java调试体系及协议

    首先,Java Platform Debugger Architecture(JPDA)是一个开放的标准,它定义了如何构建调试器和被调试的Java应用程序之间的接口。JPDA由三个主要组件组成:Java Debug Interface (JDI),Java Virtual Machine Tool...

    jdivisitor:Java库,用于使用Java调试接口(JDI)和访问者设计模式来构建自定义调试器应用程序

    JDIVisitor JDIVisitor是一个Java库,用于使用Java调试接口(JDI)和访问者设计模式来构建自定义调试器应用程序。 它从的项目中汲取了灵感。 但是,JDIVisitor避开了jdiscript的类似脚本的设计,而改用了更具Java...

    JPDA----java调试体系

    通过 JPDA,开发人员可以根据特定需求,扩展定制 Java 调试应用程序,开发出吸引开发人员使用的调试工具。 ### 丰富的 API JPDA 提供了丰富的 API,提供了许多实用的功能,例如,监控当前 Java 虚拟机的状态,设置...

    学习调试java源码学习调试java源码

    JDI是Java虚拟机工具接口的一部分,提供了调试API,而JDB则是一个命令行工具,可以用来远程或本地调试Java应用。 1. **设置断点**:在源码中设置断点是调试的第一步。你可以使用IDE(如Eclipse、IntelliJ IDEA或...

    一种基于芯片仿真VCD波形格式的Java程序自动调试方法.pdf

    本文介绍的是一种基于芯片仿真VCD波形格式的Java程序自动调试方法,该方法结合了Java开发接口(JDI)技术和Linux脚本,实现了Java程序的自动调试,并将结果保存为VCD(Value Change Dump)格式文件,以方便后续的...

    sa-jdi.jar.zip

    "sa-jdi.jar"可能是某个特定项目或服务的组成部分,其中包含了Java调试接口(Java Debug Interface, JDI)的实现。 描述中的"git-2.19.0-64-bit"指的是Git版本控制系统的一个版本,具体为2.19.0的64位构建。Git是一...

    JAVAECLIPSE下配置WINDCHILL远程调试WINDCHILL学习笔记.pdf

    调试工具直接使用 JDI 来实现调试功能。 4. **JDWP (Java Debug Wire Protocol)**: 定义了 JPDA Front-end 和 JPDA Back-end 之间通信信息的二进制格式。它是 Debugger 和 Target VM 之间通信的协议。 #### 四、...

    深入Java调试体系(JPDA-JDWP)

    JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),Java 调试线协议(JDWP),以及 Java 调试接口(JDI),本系列将会详细介绍这三个模块的内部细节、通过实例为读者揭开 JPDA 的面纱。

    java 19下载,版本 19.0.1, windows各版本

    4. **Java调试接口**(JDI)和**Java调试工具**(jdb):用于调试Java应用程序,查找并修复代码中的问题。 5. **Java性能分析器**(JFR)和**Java Mission Control**(JMC):这些工具帮助开发者监控和分析应用程序...

    javaEclipse

    在Java开发环境中,Eclipse是一款广泛使用的集成开发环境(IDE),尤其适合于Java应用程序的...在这个过程中,JPDA提供了一套完整的框架,使得开发者可以在不接触底层细节的情况下,实现高效且跨平台的Java程序调试。

    Windows Java SE Development Kit 11.0.15.1 x64 Installer

    总之,Java SE Development Kit 11.0.15.1 x64 Installer为Windows用户提供了一个强大的开发环境,包含了编写、编译、运行和调试Java应用程序所需的所有工具。随着版本的不断迭代,开发者可以期待更多的性能提升和新...

    windchill远程调试详细介绍

    Windchill 远程调试是指在 Windchill 开发环境中,使用 Java 平台调试器(JPDA)来调试远程服务器上的 Java 应用程序。JPDA(Java Platform Debugger Architecture)是 Java 平台上的调试器定义的标准体系结构,它...

    JAVA-api.rar_2017java中文api_java pro_java API_java api_java在线a

    对于`java.pro`的专业开发者,他们可能更关注高级特性,如并发编程(`java.util.concurrent`包)、JVM内存管理、Java虚拟机调试接口(JDI)、Java数据库连接(JDBC)以及Java应用程序接口(Swing或JavaFX)等。...

    JPDA文章汇总

    通过分析这些代码,我们可以了解到如何在实际项目中使用JDI接口来实现调试功能,例如创建和管理调试会话、设置断点、查看变量值等。 7. **工具集成:** 许多流行的Java开发工具,如Eclipse、IntelliJ IDEA等,已经...

    java并发编程

    JDI是一个强大的API,可以用来远程调试Java应用,特别是在多线程环境下的调试,如压缩包中的"Java进阶:使用JDI调试多线程应用程序.docx"文档可能详细介绍了如何使用JDI来定位和解决并发问题。 JDI允许开发者在运行...

    一个jsp的eclipse开发

    5. **JDI**:调试客户端使用的一组 Java 接口。 #### 三、JVM 调试参数详解 为了以调试模式启动 JVM,可以使用以下参数: - `-Xdebug`:启用调试支持。 - `-Xnoagent`:不使用默认的代理。 - `-Xrunjdwp:...

Global site tag (gtag.js) - Google Analytics