[摘自:http://lehsyh.javaeye.com/blog/581154]
在无法访问运行中的实例时,调试一个Java程序可能相当麻烦;当应用程序在远程环境下运行,并且不会在控制台或日志文件中输出任何结果时,调试工作变得更加困难。如果你需要对一个运行中的Java应用程序进行全方位调试,Sun的Java平台调试构架(JPDA)可为您提供帮助。
JPDA是一组API集合,旨在帮助你调试Java代码。J2SE自1.2.2版开始推出JPDA工具集,并在1.3.x版中将它直接包含在J2SE软件包中。
JPDA并非一个应用程序或调试工具,而是一组精心设计的接口与协议,了解这点很重要。Sun设计这一标准的目的是提供一个基础构架,以便第三方工具和调 整器能够高效利用它。还有许多利用JPDA的优秀调试器和IDE,包括一些获得广泛认可的工具,如Borland JBuilder、Oracle JDeveloper、IntelliJ IDEA、Sun NetBeans、IBM Eclipse等等。不过,Sun在它的传统命令行式调试器jdb中提供了一个参考实例。Java 1.3重新编写了jdb以支持JPDA。在本文中,我将讨论JPDA技术及它的一些实际应用。
最近使用WTP的Server功能很不爽,连tomcat服务器时java类中的任何改动都要重启服务器,一怒之下就改用JPDA了,以下是一些总结。
什么是JPDA
Java Platform Debugger Architecture(JPDA:Java平台调试架构) 由Java虚拟机后端和调试平台前端组成
1.Java虚拟机提供了Java调试的功能
2.调试平台通过调试交互协议向Java虚拟机请求服务以对在虚拟机中运行的程序进行调试
JPDA的构架
JPDA通过两个接口和协议来完成如上的说明,分别是JVMTI(Java虚拟机工具接口)、JDWP(Java调试连线协议)和JDI(Java调试接口)。
1.JVMTI定义了虚拟机应该提供的调试服务,包括调试信息(Information譬如栈信息)、调试行为(Action譬如客户端设置一个断点) 和通知(Notification譬如到达某个断点时通知客户端),该接口由虚拟机实现者提供实现,并结合在虚拟机中
2.JDWP定义调试服务和调试器之间的通信,包括定义调试信息格式和调试请求机制。Java调试线协议(JDWP)定义在调试过程和调试器前端之间传输的信息和请求的格式。它执行Java调试接口(JDI)。
3.JDI在语言的高层次上定义了调试者可以使用的调试接口以能方便地与远程的调试服务进行交互,Java语言实现,调试器实现者可直接使用该接口访问虚拟机调试服务。JDI定义用户代码级信息和请求。
JPDA 概念将调试过程分为两部分:被调试的程序(被调试者-debuggee)和JDI。JDI一般为一个调试应用程序的用户接口(或Java IDE的一部分)。被调试的应用程序在后端运行,而JDI在前端运行。在前端与后端之间有一个通信通道运行JDWP协议;因此,被调试程序与调试器可以位 于同一个系统内,也可位于不同的系统中。
从 开发者的角度,一个调试应用程序可进入任何JPDA层面。因为JDI是最高层,也最容易使用,我们推荐使用这个接口。假设一家公司用JDI开发了一个调试 器。公司能够把它用于参考实例中,它将自动与VM和Sun支持的平台协同工作,因此大多数IDE供应商采用这种方式。还可以这样,例如,参考实例在前端运 行,被调试者运行另一家公司执行JDWP(它可能运行或忽略JVMTI)的VM。
一些调试器可能建立在较低层面之上,如JDWP(例如,如果Java没有编写前端)或JVMTI(针对需要低级功能的专用调试器)。
调试器的后端负责由调试器前端向被调试者VM传输请求,如“告诉我变量X的值”;它还负责向前端传输对这些请求(包括像到达断点之类的预计事件)的响应。后端与前端利用JDWP通过一个通信通道进行通信。后端与被调试者VM利用JVMTI进行通信。
运行方式
当虚拟机的调试服务运行时,虚拟机作为调试的服务提供端,监听一个连接,而调试器通过该连接与虚拟机进行交互。目前,Windows平台的JVM提供了两种方式的连接:共享内存和 Socket连接,共享内存的服务提供端和调试端只能位于同一台机,而Socket连接则支持不同异机调试,即远程调试。
虚拟机参数设置
1.启用调试服务
-Xdebug 启用调试
-Xrunjdwp: 加载JVM的JPDA参考实现库
2.Xrunjdwp子参数(sub-options)配置
Xrunjdwp子参数的配置格式如下
-Xrunjdwp:[=],[=]...
几个例子
-Xrunjdwp:transport=dt_socket,server=y,address=8000
在8000端口监听Socket连接,挂起VM并且不加载运行主函数直到调试请求到达
-Xrunjdwp:transport=dt_shmem,server=y,suspend=n
选择一个可用的共享内存(因为没有指address)并监听该内存连接,同时加载运行主函数
-Xrunjdwp:transport=dt_socket,address=myhost:8000
连接到myhost:8000提供的调试服务(server=n,以调试客户端存在),挂起VM并且不加载运行主函数
-Xrunjdwp:transport=dt_shmem,address=mysharedmemory
通过共享内存的方式连接到调试服务,挂起VM并且不加载运行主函数
-Xrunjdwp:transport=dt_socket,server=y,address=8000,
onthrow=java.io.IOException,launch=/usr/local/bin/debugstub
等待java.io.IOException被抛出,然后挂起VM并监听8000端口连接,在接到调试请求后以命令/usr/local/bin/debugstub dt_socket myhost:8000执行
-Xrunjdwp:transport=dt_shmem,server=y,onuncaught=y,launch=d:\bin\debugstub.exe
等待一个RuntimeException被抛出,然后挂起VM并监听一个可用的共享内存,在接到调试请求后以命令d:\bin\debugstub.exe dt_shmem
启动tomcat
-Xdebug -Xrunjdwp:transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=n
以上两行是tomcat5.5.12的catalina.bat文件中的一句,可以看出tomcat在JPDA方式下是怎么启动的,启动tomcat要用catalina jpda start来启动,不能用startup.bat启动,启动前设置好JPDA_TRANSPORT,JPDA_ADDRESS就OK了
另有一篇文章http://www.blogcn.com/u2/38/21/ayufox/blog/36956440.html 介绍如何使用Eclipse构建测试平台
本文将介绍使用Eclipse JPDA,在Eclipse的开发环境下对远程运行的Java程序进行调试操作。
请按以下步骤进行(本人已经在Eclipse 3.2, JDK 1.5_08)环境下调试成功。
1. 在启动Java程序时,在Java启动命令中,加入以下参数
-Xdebug -Xrunjdwp:transport=dt_socket,address=1234,server=y,suspend=n
注: suspend参数表示,启动时,是否等待JPDA调试端连接。n表示否
2. 配置完后,就可以运行Java程序,看到如下提示,表示已经开启debug功能
Listening for transport dt_socket at address: 1234
3. 打开Eclipse, 在菜单"run"->"debug..." 弹出的对话框中,选择 Remote Java Application,新建Debug配置
* Project是运行的程序源代码项目
* Host,Port Host:运行的Java程序所在的Ip Port在Java运行命令中设置的端口
4. 完成,直接运行Debug即可。接下来,与调试本地的程序的方法相同。
linux下的java远程调试jpda+tomcat
项目放到linux服务器了,服务器的环境或者数据可能和我们本地不一样,这个时候我们可能需要远程的断点进行调试,来查看请求过程中的各个变量的值。
这里我们的eclipse就是那个调试的前台。我们需要将本地的调试平台和服务器运行的项目结合起来。
第一步:启动tomcat的jpda支持
默认情况下tomcat的启动命令是: ./catalina.sh start 但是这个命令是没有启动我们的jpda这个服务
我 们需要启动jpda服务,好在tomcat提供了集成化的命令:./catalina.sh jpda start,这样就启动了我们服务器jvm的jpda服务了。tomcat默认的jpda服务的端口是8000,这个时候我们使用命令看下 netstat -an,看看8000端口是不是已经启动了。
第二步:从本地建立jpda的断点调试前台
1、在eclipse的“Run”菜单下选择“Debug...”菜单,在弹出的对话框左边的菜单中选择“Remote Java Application”菜单,右键点击,选择“New”,这个时候弹出一个需要填写参数的对话框
2、在弹出的框中,定义项目名称,选择要断点调试的项目,Connect type(默认Standard (Socket Attach)),定义我们的web项目放在哪里(就是我们的远程虚拟机在哪里),填写他的ip以及提供的服务端口号,tomcat的这个版本是 8000.最后选择source标签,将项目的源码加入,我这里一般选择add一个java project的方式
3、切换到debug模式下,就能看到debug的相关选项都是激活状态。在本地的source文件中加断点,然后请求服务的链接,看看我们的断点调试是否成功。
以上的操作经过我本人验证过。
很 多的服务器都提供这种远程调试的接口服务,所以不要局限于tomcat可用,最主要的区别就是每个服务器提供的jpda的启动方式不同,提供的服务端口不 同,这里我们tomcat5.5提供的启动方式是catalia.sh jpda start这种命令行的方式,端口默认用8000。大家在开发的时候按照服务器提供的说明进行调试吧
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kongqz/archive/2009/03/09/3971263.aspx