Java 远程调试(Remote Debugging)

远程调试生产环境(或远程环境)的 Java 应用,以便快速定位某些在本地环境难以重现的问题。

远程部署的可能是个 Jar 包 或 Tomcat、Jetty 应用,若定位生产问题是通过反复修改 log 发包,效率就太低下了。

Java 提供了 JPDA 远程调试将本地源码与部署服务器连接,可以在本地控制断点的运行。

JPDA(Java Platform Debugger Architecture)为Java平台上的调试器定义了一个标准的体系结构。

该体系结构包括3个主要组成部分:JVM TI、JDI和JDWP。

开启Debug模式

远程Java应用以 Debug 模式启动,Java 命令时必须带上以下 JVM 参数。

1
2
3
4
5
6
# JAVA 大于 5.0 版本
java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -jar -Xms64m -Xmx128m conv-pay-provider.jar > /dev/null 2>&1 &

# JAVA 小于或等于 5.0 版本
java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n
java -Xdebug -Xrunjdwp:transport=dt_socket, address=5005,server=y,suspend=y

参数说明:

JVM 的 -X参数是非标准选项,在不同的版本的 JVM 中,参数可能不同,可通过 java -X查看参数。

  • -Xdebug:开启 Debug 模式。

  • -Xnoagent:关闭 Agent 代理。

  • -Djava.compiler=NONE:禁止 JIT 对整个 class 进行编译,只使用转译器,提高效率。

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

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

    server=y:y 表示启动的 JVM 是被调试者;n,则表示启动的 JVM 是调试器。

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

    address=5005:JVM在指定端口上监听请求。

远程调试 Spring Boot

在运行的 Spring Boot Jar 的命令上加上远程调试的 JVM 启动参数。

1
2
3
4
5
# JAVA 大于 5.0
java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -jar -Xms128m -Xmx128m demo.jar &

# JAVA 小于或等于 5.0
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -jar -Xms128m -Xmx128m demo.jar &

远程调试 Tomcat

Tomcat 为开启 JVM 远程调试的参数有:JPDA_OPTS,CATALINA_OPTS 和 JAVA_OPTS。

  • JAVA_OPTS:通常不建议使用的,因为会暴露给所有的 JVM。
  • CATALINA_OPTS:限制在Tomcat 内启效。

默认支持

看一段 Tomcat 的 catalina.sh脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if [ "$1" = "jpda" ] ; then
if [ -z "$JPDA_TRANSPORT" ]; then
JPDA_TRANSPORT="dt_socket"
fi
if [ -z "$JPDA_ADDRESS" ]; then
JPDA_ADDRESS="localhost:8000"
fi
if [ -z "$JPDA_SUSPEND" ]; then
JPDA_SUSPEND="n"
fi
if [ -z "$JPDA_OPTS" ]; then
JPDA_OPTS="-agentlib:jdwp=transport=$JPDA_TRANSPORT,address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND"
fi
CATALINA_OPTS="$JPDA_OPTS $CATALINA_OPTS"
shift
fi

Tomcat 默认为远程调试提供了命令支持:jpda,默认服务地址是 localhost,端口是:8000。在实际使用时,可通过命令行参数来设置参数。

使用 JPDA启动

1
sh /bin/catalina.sh jpda start

自定义设置

%TOMCAT_HOME%\bin 目录下创建可执行脚本文件 setenv.sh ( Windows 创建 setenv.bat ),bin 目录下的 setevn.* 额外的配置文件在 tomcat 启动时被自动加载,使用外部配置文件一直是最佳选择。配置文件加入内容:

Linux setend.sh:

1
export JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n"

若要修改默认设置,在 setenv.sh 配置文件中添加指定参数,如下:

1
export JDPA_ADDRESS="5005"

按照普通的方式启动 Tomcat 即可:

1
2
3
./startup.sh
#
./catalina.sh start

Windows setenv.bat:

1
set JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n"

如果 Tomcat 作为系统服务来运行,可右键打开 Tomcat 服务的属性对话框,在启动参数中添加:

1
2
-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n
#注意:确保每一条配置都是新的行,参数选项之间没空格

这些配置也可在设置在%TOMCAT_HOME%\bin\catalina.sh文件中:在文件第一行添加下面代码。

1
JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n"

参数名同样可以使用 JAVA_OPTSCATALINA_OPTScatalina.sh脚本有对这两个参数进行拼接。

IDEA连接远程Debug端口

远程服务以 Debug 模式启动成功后,本地 IDEA 就可以连接上远程服务对应的 Debug 端口,就可以打断点调试了。

在源码工程创建一个远程调试的配置,如下:

  1. Run > Edit Configurations > Add New Configurations > Remote
  2. Configuration:输入远程服务的 IP 和 端口
  3. Use module classpath:选择本地源代码的模块
  4. 运行此配置

IDEA 配置远程调试

相关参考

  1. Java远程调试(Remote Debugging)的那些事
  2. How to Remotely Debug Application Running on Tomcat From Within Intellij IDEA
  3. JPDA(jaa platform debugger architecture)
  4. JVM远程调试为什么要禁用JIT -Djava.compiler=NONE
  5. JVM启动参数与原理
作者

光星

发布于

2021-12-27

更新于

2022-06-17

许可协议

评论