eclipse远程调试tomcat中发布的项目实战

这是一个工具说明文章,在实际环境和生成环境总会出现或多或不一样的情景。这不场景产生的问题,变相找的解决方案就是这篇笔者想要阐述的内容。


场景:项目打包发布后再window中访问以及页面跳转正常,但是在linux进行打包发布的时候确发现使用springMvc跳转时候不好使。


那么如何调试远程Tomcat呢?

           远程调试Tomcat,本质上就是远程调试JVM。倒不是需要了解JVM自身的运行细节,而是要了解JVM上应用程序的运行细节。无论如何,我们都要获取JVM运行时的内部信息(比如查看调试信息),并对JVM的运行流程进行控制(比如单步执行),才能达到调试的目的。这个事情光靠调试器本身,肯定是做不到的。不然,JVM的安全性就大打折扣了。除非JVM提供某种“后门”,供调试器查询一些运行时信息,并允许调试器发送一些控制命令。不得不感慨,JVM的强大。从J2SE 1.4.2开始,就已经提出并实现了JavaTM Platform Debugger Architecture,简称JPDA。



JPDA简介

           顾名思义,JPDA为Java平台上的调试器定义了一个标准的体系结构。该体系结构包括3个主要组成部分:JVM TI、JDI和JDWP。

          JVM TI的全称是Java Virtual Machine Tool Interface,它定义了JVM为了支持调试而必须提供的功能及相应的访问接口。这些访问接口是以本地语言的形式提供的,由JVM(比如Sun公司的HotSpot VM)负责实现。不过,JVM TI只是JVM提供的一系列函数,调试器(特别是远程的调试器)如何调用呢?其实啊,JVM TI的直接客户端并不是调试器,而是一个称为“JPDA back-end”的东东。这个东东应该是属于JVM的一部分,在SUN JRE的bin目录下可以找到jdwp.dll(jdwp.so)的库文件,这就是JPDA back-end的实现。按我理解,JPDA back-end提供了各种访问方式(共享内存,Socket),通过这些方式接收调试器的请求,然后调用JVM TI接口。

          JDI的全称是Java Debug Interface,它定义了访问JVM TI接口的高层API,以纯Java语言提供,由JDK实现(在Sun JDK的tools.jar可以找到)。调试器直接使用JDI来实现调试的功能。与JPDA back-end相对应,JDI实现的角色就是JPDA front-end。

         JDWP的全称是Java Debug Wire Protocol,它定义了JPDA front-end和JPDA back-end之间通讯信息的二进制格式。这里的通讯信息主要包括两种:调试器发送给JVM的请求信息和JVM发送给调试器的调试信息。

         总结一下,调试器调用JDK提供的JDI实现(JPDA front-end),经由JDWP协议,和JVM自带的JPDA back-end(jdwp.dll, jdwp.so, ...)进行通讯。JPDA back-end通过调用JVM TI接口,从而获知调试信息,或发送控制命令。然后,JPDA back-end将调试信息或命令执行结果,通过JDWP协议,返回给调试器


如何启用JPDA?

        默认情况下,JVM并没有启用JPDA back-end。需要在启动JVM的命令行加载以下参数:

       

   -Xdebug -Xrunjdwp:transport=dt_socket, address=8000,server=y,suspend=y

-Xdebug        启用调试特性

-Xrunjdwp     启用JDWP实现,它包含若干子选项:

transport=dt_socket     JPDA front-end和back-end之间的传输方法。dt_socket表示使用套接字传输。

address=8000   JVM在8000端口上监听请求。

server=y       y表示启动的JVM是被调试者。如果为n,则表示启动的JVM是调试器。

suspend=y   y表示启动的JVM会暂停等待,直到调试器连接上,n则表示不会暂停等待。

 

ps:suspend=y这个选项很重要。如果你想从Tomcat启动的一开始就进行调试,那么就必须设置suspend=y。这些参数有些信息会映射到eclipse中。


如何在tomcat中启动JVM时候加载以上参数呢?

            只要Tomcat启动时,启用了JPDA,那么就可以被调试。而Tomcat默认是不启用JPDA的,需要我们手动开启。开启JPDA的方法也很简单,对Tomcat的启动脚本做点修改,把启动JPDA的命令行参数添加进去,就可以了。


           分析下tomcat中的启动命令:以Windows为例

          startup.bat        //启动Tomcat

          shutdown.bat   //停止Tomcat

          catalina.bat       //包含启动/停止Tomcat的核心逻辑


以我的tomcat7(window版本)执行catalina.bat命令如下:

可以发现catalina的命令的指令特别的多,不难看出startup.bat,其实就是执行catalina.bat start;shutdown.bat,其实就是执行catalina.bat stop。


由此在jvm中开启JPDA并有三种方式(已window为例):

1.在startup.bat中开启

                      在startup.bat中首行或者末尾行添加:

SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000

2.自定义bat文件启动

                    复制一份startup.bat,取名为jpda.bat放在同目录下面.

                    修改:

                  call "%EXECUTABLE%" start %CMD_LINE_ARGS%

                  修改成

                  call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

不过,-Xdebug -Xrunjdwp:transport=dt_socket, address=8000,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=8000
set JPDA_SUSPEND=y

例如本人下的配置:



3.在catalina.bar中开启

                    同样的在catalina.bat中的首行或者末尾行添加:

SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
               


在eclipse中进行配置远程debug参数


在本地访问远程项目,此时本机eclipse就会进行断点模式。完结!

展开阅读全文

没有更多推荐了,返回首页