使用Java Debug Interface(JDI)调试多线程应用程序

多线程环境下的程序调试是让开发者头痛的问题。在 IDE 中通过添加断点的 方式调试程序,往往会因为停在某一条线程的某个断点上而错失了其他线程的执 行,线程之间的调度往往无法预期,并且会因为断点影响了实际的线程执行顺序 。因此,在调试多线程程序时,开发者往往会选择打印 Trace Log 的方式来帮 助调试。

使用 Log 来帮助调试的问题在于,开发者往往无法预期哪些关键点需要记录 ,于是在整个程序的调试过程中,需要不断的加入 Log 调用,编译生成可执行 程序并部署,这对于大尺寸的软件开发项目无疑是噩梦,会直接影响到开发效率 。

有没有一种办法,可以独立于程序代码,能在运行期间绑定到程序上并获取 程序运行过程当中的关键信息呢?更重要的,这种方法应该是可定制的,开发者 可以通过少量的努力,就可以达到特定的调试目的。答案是肯定的。通过使用 java Debug Interface(JDI),开发者可以快速开发定制出适用于自己的线程 Profiling 工具。这样的工具独立于主程序,并且可高度定制。在接下来的文章 中,我们将介绍如何实现该工具。

认识 JPDA 和 JDI

从 J2SE 1.3 开始,Java 开始提供了一套叫做 Java Platform Debugger Architecture(JPDA)的架构,开发者可以通过这套架构来开发调试用程序。这 套架构被主流的 Java IDE(如 Eclipse、NetBeans 等)广泛地采用。

具体来说,JPDA 不仅仅是一套 API 的组合,也不只是一个具体的工具。这 套架构提供了从目标程序、调试双方的信息协议,到供开发者使用的结构调用, 都一一做出了定义。在 J2SE 5.0 中,它由三个部分组成:

Java Virtual Machine Tools Interface(JVMTI),是一套低级别的 native 接口。它定义了 Java 虚拟机所必需为调试提供的服务接口。JVMTI 在 Java 5.0 之前的前身是 JVMDI(Jave Virtual Machine Debug Interface)。

Java Debug Wire Protocol(JDWP),定义了调试双方信息和请求的文本格 式。

Java Debuger Interface(JDI),定义了代码级别的调试接口。

从开发者的角度来看,调试工具的开发既可以基于 JVMTI 也可以基于 JDI。 JVMTI 是 native 接口,使用起来相对复杂,并且需要 C 语言的基础,因此, 在本文中,我们将介绍如何使用 JDI 这种最上层的方式来开发 Java 调试程序 。

需求分析

在接下的部分,我们将介绍如何使用 JDI 来开发一个用来调试多线程程序的 工具。在开始前,让我们先列出这个工具需要满足的功能:

独立于目标应用程序的。

应该足够简单,并且能在通过少量的代码修改就能完成集中配置,这样是帮 助开发者不需要付出太多的努力就能开始调试自己的多线程程序。

能够抓取足够的信息,比如说异常的信息,程序调用过程中的变量值等等。

所生成的 Log 应该足够清晰,能够按不同的线程来分离记录,而不是按照时 间的顺序来生成每一条记录,否则会给调试带来不便。

实现

在文章最后的 示例代码 中,我们展示了一个典型的基于 JDI 的调试工具逻 辑,并且用它来 Profile 一个简单的多线程程序的执行。根据前面所提到的需 求,代码展示了线程运行栈快照、方法调用的入口参数值收集、异常过滤定制、 类过滤配置、线程 Log 记录等功能。具体来说:

独立于目标程序

分析工具可以通过如下方式启动:

java Trace options class args

支持的 options 参数:

-output 文件名:工具生成的 Log 的路径

class 是目标程序的入口类,args 为目标程序的输入参数

时间: 2024-12-02 04:50:59

使用Java Debug Interface(JDI)调试多线程应用程序的相关文章

怎么在java项目运行时调试bug

问题描述 怎么在java项目运行时调试bug 如题,怎么在java项目运行时调试bug?这是一道面试题,感觉没思路啊. 解决方案 debug模式,log4j打印日志,单步运行打断点 解决方案二: 首先应该通过BUG的表现确定BUG可能产生的范围.如果是数据表现,那么应该关注数据操作部分的代码,简单的错误,通过代码复查应该能排除.如果是异常表现,那么看一下异常信息,获取错误代码行,如果有经验应该能直接排除.怎么看都觉得自己代码正确(貌似都这赶脚)...好吧,各种IDE工具都提供DEBUG功能,在预

利用C#线程窗口调试多线程程序

  从网上的资料判断,调试多线程程序似乎就一下3种方法. 1.在日志的某个地方写日志文件. 优点:不会干扰程序的执行,特别是对网络的多线程通信. 缺点:每次都需要打开日志文件以查看进程运行的信息. 2.利用断点进行调试. 优点:直观,可以直接看到运行过程的值 缺点:在多个线程设置断点,可能让程序跳来跳去,还需要额外地分出一部分精力用来理清程序的逻辑 3.利用弹出窗口来查看进程调试的信息. 优点;直观 缺点;在调试网路通信的时候,使得通信的过程产生延时,导致通信失败. 4.利用vs2010自带的线

初学Java写的第一个多线程程序

程序|初学|多线程 /** 文件名 : FirstTread.java 描述 :初学Java写的第一个多线程程序 作者: 慈勤强 cqq1978@yeah.net 参考:http://java.sun.com **/ import java.io.*;import java.net.*; public class FirstTread extends Thread{ public void run() { int i=0; try { String hostname = "www.flashem

用Java实现多线程服务器程序

---- 摘要:在Java出现之前,编写多线程程序是一件烦琐且伴随许多不安全因素的事情.利用Java,编写安全高效的多线程程序变得简单,而且利用多线程和Java的网络包我们可以方便的实现多线程服务器程序. ---- Java是伴随Internet的大潮产生的,对网络及多线程具有内在的支持,具有网络时代编程语言的一切特点.从Java的当前应用看,Java主要用于在Internet或局域网上的网络编程,而且将Java作为主流的网络编程语言的趋势愈来愈明显.实际工作中,我们除了使用商品化的服务器软件外

Java技术体验:HTTP多线程下载,端口侦听和自启动服务

一个网友正好需要这个东西,我就把几个技术整合到了一起.包括三个部分,实现时也是逐个做到的 多线程的文件下载,HTTP协议 把这个功能做成一个HTTP的服务,侦听在某个端口上,方便非Java的系统使用 把这个功能封装为一个Windows服务,在机器启动时可以自动启动 我们逐个看程序. 一.多线程下载 这个主要使用了HTTP协议里面的一个Range参数,他设置了你读取数据的其实位置和终止位置. 经常使用flashget的用户在查看连接的详细信息时,应该经常看到这个东西.比如 Range:bytes=

网页-Android debug模式下调试和直接运行的问题

问题描述 Android debug模式下调试和直接运行的问题 我再使用webview控件加载一个webview的时候出现了白屏的现象 W/webcore﹕ skip viewSizeChanged as w is 0 这个警告 我使用debug模式下调试不会现象网页正常显示 直接运行和打成apk包的时候就会出现网页加载完成而页面不显示

java 线程池 程序顺序-java多线程时程序运行完成为什么不会自动关闭退出?(木有钱了,求指教)

问题描述 java多线程时程序运行完成为什么不会自动关闭退出?(木有钱了,求指教) 粘贴的大致代码如下: public static void main(String[] args) { int thread=0; ExecutorService pool = Executors.newFixedThreadPool(15);// 创建一个线程池 for (int i =666; i <= 888; i++) { for (int j = 0; j < 19; j++) { MyClass t

vs-visual studio调试多线程的问题

问题描述 visual studio调试多线程的问题 有一个前台页面定时刷新,调试的时候一定间隔发一个请求过来,导致调试的时候短点来回跳,怎么设定只调试第一个请求? 解决方案 你可以把定时器的请求先注释掉调试嘛,或者用TRACE的方式调试,打印信息到output窗口. 解决方案二: 收到数据后把定时器关掉,或者下断点加上条件判断 解决方案三: 应该可以尝试加入断点条件. 解决方案四: 调试多线程里的代码还是直接打log日志看比较好,尤其是这种时间间隔特别短的,有的时候设断点后,可能会影响程序整体

线程间通讯-Java写交易客户端(多线程、对象数据传送等简单问题)

问题描述 Java写交易客户端(多线程.对象数据传送等简单问题) 有如下几个类: 1.Ticker类//此Ticker为简单java类,其属性与服务器传来的json字段对应,通过Decoder类反系列化json//反系列化以后的数据,用以做逻辑判断,符合逻辑,则向服务器发出某种请求 public class Ticker implements Serializable { private static final long serialVersionUID = 2015022601L; priv