在Intellij下远程调试tomcat应用(含tomcat源码调试)

环境

服务器:

  • 操作系统:centos6
  • jdk:1.7
  • tomcat:8.5.9

本地:

  • 操作系统:mac osx 10.11.6
  • jdk:1.7
  • intellij:2016.2
  • tomcat:8.5.9(本地也需要下载tomcat)

应用调试步骤

java应用远程调试都是基于jpda体系,所以我们需要将tomcat通过jpda的方式启动,即可对tomcat进行远程调试。

一、服务端tomcat配置

假设服务端tomcat所在目录为:/etc/tomcat/。对于tomcat来说,所有运行相关的脚本都位于bin文件夹下,而catalina.sh是启动tomcat最为核心的脚本。为了使得tomcat能够支持远程调试,我们需要设置jpda相关的参数,但是tomcat官方建议我们不要直接修改catalina.sh里面定义的参数,而是将自定义的参数值设置在setenv.sh脚本中,证据如下:

1
2
3
4
# Environment Variable Prerequisites
#
# Do not set the variables in this script. Instead put them into a script
# setenv.sh in CATALINA_BASE/bin to keep your customizations separate.

tomcat里定义的jpda参数有:

  • JPDA_TRANSPORT:设置jpda传输方式,默认为dt_socket,此参数一般保持默认值即可。
  • JPDA_ADDRESS:服务端jpda监听的地址和端口,默认为localhost:8000,即本地的8000端口。此参数需根据实际情况进行修改。比如在本文场景中,我们需要远程调试tomcat,所以不能监听在本地,否则外网无法访问。
  • JPDA_SUSPEND:设置应用程序是否一启动就挂起,等待客户端调试器连接,默认为”n”也就是不挂起,若需要设置为挂起则修改为”y”。
  • JPDA_OPTS:若用户设置了该参数,则脚本执行时会忽略上述三个参数,直接拿JPDA_OPTS的值作为jpda的启动参数。
1
-agentlib:jdwp=transport=dt_socket,address=localhost:8000,server=y,suspend=n

我们需要根据自己的实际情况设置合适的参数,具体设置的步骤如下:

  1. 在bin文件夹下新建setenv.sh并编辑:

    1
    2
    # cd /etc/tomcat/bin
    # vim setenv.sh
  2. 设置JPDA_ADDRESS的值为0.0.0.0:8000

    1
    JPDA_ADDRESS=0.0.0.0:8000

    保存退出。

  3. 以jpda的方式启动tomcat:

    1
    # ./catalina.sh jpda start

    此时tomcat已经以jpda的方式启动,并且向外网开放了8000端口等待客户端发送调试命令。

二、Intellij配置

接下来我们需要配置intellij,具体步骤如下:

  1. 首先打开Run/Debug Configuration窗口:

  2. 点击左上角的➕号,添加一个Remote Tomcat:

  3. 填写Server配置项,需要配置的有配置名称、本地tomcat路径以及tomcat所在的host和开放的端口:

  4. 配置debug所需的参数。在本例中,由于我们在服务端的tomcat配置的是dt_socket,端口为8000,所以在这里我们也需要配置为socket和8000端口:

  5. 选择刚才的配置(比如在本例中为开发机),然后点击debug图标,打断点,开始远程调试:

调试tomcat源码

在某些情况下,我们需要调试tomcat自己的运行情况,比如为何应用里配置的listener没有加载成功,或者想研究tomcat的应用机制,这个时候,我们就需要直接调试tomcat的源码。

一、下载源码

俗话说,巧妇难为无米之炊,我们首先需要下载tomcat的源码。在本例中,我们tomcat的版本为8.5.9,下载地址请点击。下载成功后解压,我们假设源码目录位于:~/tomcat/

二、导入源码

我们需要将源码导入到intellij中,为接下来的调试打好基础。

  1. 下载下来的tomcat是一个ant工程,为了方便,我们首先将其转化为一个maven工程,这样我们就不需要关心依赖包的下载问题。我们在源码目录下新建pom.xml文件,pom的内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>Tomcat8.0</artifactId>
    <name>Tomcat8.0</name>
    <version>8.0</version>
    <build>
    <finalName>Tomcat8.0</finalName>
    <sourceDirectory>java</sourceDirectory>
    <testSourceDirectory>test</testSourceDirectory>
    <resources>
    <resource>
    <directory>java</directory>
    </resource>
    </resources>
    <testResources>
    <testResource>
    <directory>test</directory>
    </testResource>
    </testResources>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3</version>
    <configuration>
    <encoding>UTF-8</encoding>
    <source>1.7</source>
    <target>1.7</target>
    </configuration>
    </plugin>
    </plugins>
    </build>
    <dependencies>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>ant</groupId>
    <artifactId>ant</artifactId>
    <version>1.7.0</version>
    </dependency>
    <dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
    <version>1.6.2</version>
    </dependency>
    <dependency>
    <groupId>javax.xml</groupId>
    <artifactId>jaxrpc</artifactId>
    <version>1.1</version>
    </dependency>
    <dependency>
    <groupId>org.eclipse.jdt.core.compiler</groupId>
    <artifactId>ecj</artifactId>
    <version>4.5</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.easymock/easymock -->
    <dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>3.2</version>
    <scope>test</scope>
    </dependency>
    </dependencies>
    </project>
  2. 然后我们将源码导入到intellij中:

    在弹出来的对话框中选择刚才源码所在的目录,并且作为Maven工程导入,即可导入成功。

  3. 为了避免待会执行test时出现问题,我们需要删除test/util/TestCookieFilter.java文件。

三、配置远程调试

配置步骤与第二部分介绍的配置步骤相同。唯一需要注意的是,服务端的tomcat在配置jpda参数时,可以将JPDA_SUSPEND设置为y,这样tomcat启动之后不会执行任何代码,而是挂起,直到客户端连上来后才会继续执行。

其他

如果存在服务端jpda已经启动,但是客户端无法连接的情况,请检查防火墙。

参考资料

  1. Tomcat8源码学习之导入到IDEA
坚持原创技术分享,您的支持将鼓励我继续创作!