`

工作日志:远程调试的方法(Tomcat与JDPA)

阅读更多

工作日志:远程调试JVM

 

归档时间:2011-9-28


一、远程调试的战略目标
      伴随系统上线后,由于服务器操作权限没有面向系统设计人员开放,只能通过系统的操作日志以及错误日志来分析性能以及错误处理。但是有时候,由于错误信息没有针对性就给系统设计人员分析问题带来了难度与不便,如果系统设计人员能够对已经上线部署在远程端面Java虚拟机后端的系统进行实时调试的情况下,该问题将变得迎刃而解,我要激动的说一声,那都不是事!
      正巧我对Tomcat的构架有着极其深厚的兴趣,早在2006年就开始参考HowTomcatWorks文献等资料结合Tomcat的源代码在始终在研究Tomcat工作的基本构架到现在已经有5个年头了。也是期盼能够设计出一个类似于该容器的构架。
步入正题,如何远程调试Tomcat。通过博客以及相关社区查了一些资料,相关的文章还是很多的。我简单梳理了一下解决方案及原理,以便日后作为参考,顺便分析一下Tomcat的启动脚本。大量的文章都介绍了JPDA,那么我也从此入手解开谜底。
二、JPDA概要
      1. JPDA(Java Platform Debugger Architecture,Java平台调试架构) ,由Java虚拟机后端和调试平台前端组成, JPDA为Java平台上的调试器定义了一个标准的体系结构。该体系结构包括3个主要组成部分:JVM TI(Java虚拟机工具接口)、JDI(Java调试连线协议)和JDWP(Java调试接口)。
      2. JVM TI(JavaVirtualMachineToolInterface),它定义了JVM为了支持调试而必须提供的功能及相应的访问接口。包括调试信息(Information譬如栈信息)、调试行为(Action譬如客户端设置一个断点)和通知(Notification譬如到达某个断点时通知客户端),该接口由虚拟机实现者提供实现,并结合在虚拟机中。
这些访问接口是以本地语言的形式提供的,由JVM负责实现。这里有个理解上得难度,JVM负责实现是怎么回事?我的理解是JVM TI只是JVM提供的一系列函数,JVM TI就是在桌子上的苹果菠萝,他告诉我们你可以吃苹果菠萝,可是你进不去房间,只能依靠一个服务人员来取,那么你要吃什么,怎么吃呢?他不管。那谁来管?谁来调用他谁就来管呗?JVM TI的直接客户端并不是调试器,而是 “JPDA back-end”,属于JVM的一部分,在SUN JRE的bin目录下可以找到jdwp.dll(jdwp.so)的库文件。这就是JPDA back-end的实现。也就是说JPDA back-end提供了各种访问方式,吃的方式(共享内存,Socket),通过这些方式接收调试器的请求,然后调用JVM TI接口,他来决定你怎么吃。
      3. JDI(Java Debug Interface),在语言的高层次上定义了调试者可以使用的调试接口以能方便地与远程的调试服务进行交互,它定义了访问JVM TI接口的高层API,以纯Java语言实现,调试器实现者可直接使用该接口访问虚拟机调试服务。调试器直接使用JDI来实现调试的功能。与JPDA back-end相对应,JDI实现的角色就是JPDA front-end。如同上面的例子,JDI就是桌子和那个服务员,提供了访问的平台,通道。
      4. JDWP(Java Debug Wire Protocol),它定义了JPDA front-end和JPDA back-end之间通讯信息的二进制格式。这里的通讯信息主要包括两种:调试器发送给JVM的请求信息和JVM发送给调试器的调试信息。调试服务和调试器之间的通信,包括定义调试信息格式和调试请求机制。就是你要吃什么?请求是什么、你得告诉服务员你要什么,不过这个服务员是个老毛子,你得跟翻译说你的请求,翻译帮你规范你的语言,命令他才明白。
      5. 阶段目标达到!Okey。我来总结一下吧,本地调试器 调用JDK提供的JDI实现 (JPDA front-end),经由JDWP协议 ,和JVM自带的JPDA back-end (jdwp.dll, jdwp.so, ...)进行通讯。JPDA back-end 通过调用JVM TI接口 ,从而获知调试信息,或发送控制命令。然后,JPDA back-end 将调试信息或命令执行结果,通过JDWP协议 ,返回给本地调试器 。呵呵有点乱,那么我举个傻瓜和女孩的例子。有一天一个可爱的女孩(本地调试器)来到一家餐厅Java,这家酒店的经理叫做JPDA,安排女孩到JDI包房,并安排傻瓜JPDA back-end服务女孩。傻瓜JPDA back-end拿来了菜单JDWP,女孩没有看菜单JDWP就告诉傻瓜JPDA back-end要吃苹果,傻瓜JPDA back-end说苹果是个神马东西,菜单JDWP没有!并威胁说小心黑社会Error来。女孩害怕了,NND进了黑店了。没办法只能够按照菜单JDWP来点菜了。点菜后,傻瓜JPDA back-end将厨师JVM TI叫来了JPDA包房做饭告诉女孩我们不是黑店,我们是有原则协议的!厨师大哥终于做好了,并由JPDA back-end,按照菜单JDWP交给女孩。这么说就清晰明了了。呵呵!
      6. 在深入一点,我们来看看他的运行方式,那么就能分析清楚了,当虚拟机的调试服务运行时,虚拟机作为调试的服务提供端,监听一个连接,而调试器通过该连接与虚拟机进行交互。目前,Windows平台的JVM提供了两种方式的连接:共享内存和 Socket连接,共享内存的服务提供端和调试端只能位于同一台机,而Socket连接则支持不同异机调试,即远程调试。哈哈,来吧,实践才是王道啊

 

三、第一步:启动tomcat的jpda支持
      1.虚拟机参数设置
         1.1启用调试服务
           -Xdebug 启用调试
           -Xrunjdwp:<sub-options> 加载JVM的JPDA参考实现库
         1.2 Xrunjdwp子参数(sub-options)配置
           Xrunjdwp子参数的配置格式如下
           Xrunjdwp:<name1>[=<value1>],<name2>[=<value2>]...
         1.3 transport=dt_socket
           JPDA front-end和back-end之间的传输方法。dt_socket表示使用套接字传输。
         1.4 address=8000
           JVM在8000端口上监听请求。
         1.5 server=y
           y表示启动的JVM是被调试者。如果为n,则表示启动的JVM是调试器。
         1.6 suspend=y
           y表示启动的JVM会暂停等待,直到调试器连接上。
           suspend=y这个选项很重要。如果你想从Tomcat启动的一开始就进行调试,那么就必须设置suspend=y。
      2. 配置:

-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 <address>执行,<address>是可用的共享内存

 

      3. Tomcat的启动脚本
      只要Tomcat启动时,启用了JPDA,那么就可以被调试。而Tomcat默认是不启用JPDA的,需要我们手动开启。开启JPDA的方法也很简单,对Tomcat的启动脚本做点修改,把启动JPDA的命令行参数添加进去,就可以了。
          3.1 Windows环境的启动
            在Tomcat发行版的bin目录下,有N多脚本,其中与Tomcat启停有关的脚本是:
            startup.bat //启动Tomcat
            shutdown.bat //停止Tomcat
            catalina.bat //包含启动/停止Tomcat的核心逻辑
            startup.bat和shutdown.bat都是通过调用catalina.bat来实现启动和停止的功能,因此他俩的代码都很少。主要的逻辑都在catalina.bat中。
            catalina.bat是个强大的脚本,通过参数,可以执行各种动作,包括debug run start stop version等。
如果我们直接执行catalina.bat,就可以看到它的用法说明:



            startup.bat,其实就是执行catalina.bat start;shutdown.bat,其实就是执行catalina.bat stop。
不难猜到,我们可以写一个jdpa.bat,直接调用catalina.bat jpda start,应该就可以启用JPDA。我们拷贝一份startup.bat,把下面这行
            call "%EXECUTABLE%" start %CMD_LINE_ARGS%
                  修改成
            call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

            不过,-Xdebug -Xrunjdwp:transport=dt_socket, address=5050,server=y,suspend=y,这些选项参数怎么传递给catalina.bat呢?
            看看catalina.bat前面的注释,server的值默认就是y,transport的值是变量 JPDA_TRANSPORT,address的值是变量JPDA_ADDRESS,suspend的值是变量JPDA_SUSPEND 。如果没有显式地复制,这些变量的值默认是dt_shmem jdbconn n(默认值表示使用共享内存作为传输方式)。这些默认值不是我们需要的,Eclisep的远程调试目前只支持套接字传输。在调用catalina.bat jpda start之前,我们给这些变量设置恰当的值:
            set JPDA_TRANSPORT=dt_socket
            set JPDA_ADDRESS=5050
            set JPDA_SUSPEND=y
            call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%
            创建jpda.bat,复制startup.bat修改文件名称为japa.bat。之后,将以上4行代码复制到新建成的japa.bat最后部分,哈哈这样我们就成功建立了一个jpda的批处理!
            然后,直接执行jpda.bat,Tomcat就运行在JPDA可调式模式下:

 

          从上图可以看出,Tomcat的JPDA使用套接字传输,监听在5050端口。Tomcat的启动已经暂停,只有调试器连接上来,才会继续启动。
我把jpda.bat的完整内容列在下面,其中黑体部分,在startup.bat基础上添加的代码:

@echo off
if "%OS%" == "Windows_NT" setlocal
rem Guess CATALINA_HOME if not defined
set CURRENT_DIR=%cd%
if not "%CATALINA_HOME%" == "" goto gotHome
set CATALINA_HOME=%CURRENT_DIR%
if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome
cd ..
set CATALINA_HOME=%cd%
cd %CURRENT_DIR%
:gotHome
if exist "%CATALINA_HOME%/bin/catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome
set EXECUTABLE=%CATALINA_HOME%/bin/catalina.bat
rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find %EXECUTABLE%
echo This file is needed to run this program
goto end
:okExec
rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs
set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=5050
set JPDA_SUSPEND=y
call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%
:end_
 


         3.2 Linux环境的启动
            在Linux系统中已经Tomcat已经配置了Jpda,可是啊,默认情况下tomcat的启动命令是: ./catalina.sh start 但是这个命令是没有启动我们的jpda这个服务。
            我们需要启动jpda服务,好在tomcat提供了集成化的命令:./catalina.sh jpda start,这样就启动了我们服务器jvm的jpda服务了。tomcat默认的jpda服务的端口是8000,这个时候我们使用命令看下 netstat -an,看看8000端口是不是已经启动了。如果我们想修改端口该如何呢?呵呵,经过分析我们知道Jpda的工作细节,那么也像Windows环境的启动一样
            我们将
                  export JPDA_ADDRESS=8000
            修改为
                  export JPDA_ADDRESS=5050
            由于没有服务器权限,就委托运维部代我部署了一下,已经成功测试。


四、第二步:在Eclipse中远程调试Tomcat
      首先将Tomcat的源代码分为container、connectors、jasper、servletapi 、build五个项目,导入到Eclipse中。启动相关的代码主要在container中,就以它为当前项目,打开”Debug Configurations“对话框。
然后创建一个”Remote Java Application“,Connection Type选择”Standard (Socket Attach)“,Host填写localhost(Tomcat所在的主机地址),Port填写5050。最后点击”Apply“保存。

 



      首先确保已经执行了jpda.bat,Tomcat正在等待调试器连接;然后执行上述的Debug Configuration,Eclipse就可以连上Tomcat。
      Tomcat的启动是从Bootstrap的main方法开始,我在登陆代码处设置了断点,Tomcat的启动就停在了这一行:




PS:如果在配置的时候有什么问题,欢迎大家联系,并且指正不足与错误。

 

 

 

分享到:
评论

相关推荐

    JDPA-开源

    “ Java声明式编程API”(JDPA)使用注释为Java提供了声明式编程支持,从而使开发人员可以定义参数约束,接口协定,转换,拦截器等。

    基于百度地图实现的定位功能.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    加载本地图片,绝对不会出现OOM.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    2015年中国移动电子竞技游戏发展趋势报告(1).zip

    2015年中国移动电子竞技游戏发展趋势报告(1).zip

    CKplayer-v6.8.zip

    ckplayer是一款在网页上播放视频的免费的播放器,功能强大,体积小巧,跨平台,使用起来随心所欲。 CKplayer播放器主要以adobe的flash(所使用的版本是CS5)平台开发,所以在支持flash插件的平台和浏览器上都可以使用,而无需下载其它插件,如果你需要修改完整版里提供的相关的flash源文件,请使用adobe的flash cs5以上版本打开源文件修改。 ckplayer同时也支持

    46.书籍学习平台的设计与实现-Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)论坛

    46.书籍学习平台的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)论坛,公告,付费专区,免费专区,销售,会员办理,书籍分类 详细设计文档链接:http://t.csdnimg.cn/GSeDN 内容概要: 全套项目源码+详尽文档,一站式解决您的学习与项目需求。 适用人群: 计算机、通信、人工智能、自动化等专业的学生、老师及从业者。 使用场景及目标: 无论是毕设、期末大作业还是课程设计,一键下载,轻松部署,助您轻松完成项目。 项目代码经过调试测试,确保直接运行,节省您的时间和精力。 其他说明: 项目整体具有较高的学习借鉴价值,基础能力强的可以在此基础上修改调整,以实现不同的功能。

    密码学实验报告2.docx

    密码学实验报告2.docx

    各种旋转动画的ImageView(1).zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    S7200基本编程指令.ppt

    S7200基本编程指令.ppt

    基于python+OpenCV的火车票识别源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于python+OpenCV的火车票识别源码+使用文档+全部资料(优秀项目).zip基于python+OpenCV的火车票识别源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    WordPress.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    移动机器人机械臂的设计小论文.doc

    移动机器人机械臂的设计小论文.doc

    基于Python+OpenCV+tinker的指纹识别系统,使用的硬件为AS608源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于Python+OpenCV+tinker的指纹识别系统,使用的硬件为AS608源码+使用文档+全部资料(优秀项目).zip基于Python+OpenCV+tinker的指纹识别系统,使用的硬件为AS608源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    xiuno模板知乎蓝魔改版源码附多个插件.zip

    xiuno模板知乎蓝魔改版源码附多个插件

    2022年 【24页】从孪生到融生,AIGC成为长期方向.zip

    2022年 【24页】从孪生到融生,AIGC成为长期方向.zip

    [信息与通信]使用EMIF将Xilinx_FPGA与TI_DSP平台接口.pdf

    [信息与通信]使用EMIF将Xilinx_FPGA与TI_DSP平台接口.pdf

    基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    仿QQ消息列表(ListView)滑动删除效果源码.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    最新招标流程图.pdf

    1.招标投标活动不受地区或者部门的限制。任何单位和个人不得违法限制或者排斥本地区、 本系统以外的法人或者其他组织参加投标,不得以任何方式非法干涉招标投标活动。 2.招标人设有标底,标底必须保密 3.可以不招标的情况之一都可以不招标:①不可替代②采购人自行建设、生产或提供③已通 过招标方式特许的④需要向原中标人采购的,否则影响配套要求的,但是不得超过合同金额 的10%⑤国家规定的其他特殊情况

Global site tag (gtag.js) - Google Analytics