tomcat启动报错:transport error 202: bind failed: Address already in use 之如何正确开启debug

在开发环境tomcat启动的过程中遇到了这样一个错误:

ERROR: transport error 202: bind failed: Address already in use
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [debugInit.c:750]

看错误信息可以很明显地得出错误原因是端口占用,但是找遍了tomcat sever.conf中监听的端口,通过netstat -apn | grep port命令查看,没有发现它们被占用。
随后通过进一步搜索关键词JDWP等可以得出是debug端口被占用了。那么,tomcat的debug模式是如何开启的呢?

JPDA服务

JPDA(Java Platform Debugger Architecture) 是 Java 平台调试体系结构的缩写,它由三部分组成: Java 虚拟机工具接口(JVMTI),Java 调试线协议(JDWP)以及 Java 调试接口(JDI)。

  • JVMTI是最底层的,由虚拟机直接提供;
  • JDWP则定义了调试器与被调试器之间的通信格式;
  • 通过JDI,开发人员可以通过调试器很方便地控制被调试器的运行,像Eclips和Idea这类的开发工具就是实现了JDI。

详细的JPDA原理可以参看:深入JAVA调试体系

Tomcat下开启Debug

tomcat目录下使用以下命令可以在JPDA下开启debug:

bin/catalina.sh jpda start

在bin/catalina.sh文件中我们可以看到代码如下:

if [ "$1" = "jpda" ] ; then
  if [ -z "$JPDA_TRANSPORT" ]; then
    JPDA_TRANSPORT="dt_socket"
  fi
  if [ -z "$JPDA_ADDRESS" ]; then
    JPDA_ADDRESS="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

通过以上代码,我们可以发现,有三个参数可以对JPDA进行配置:

  • JPDA_ADDRESS:指定JPDA传输端口,默认是8000;
  • JPDA_TRANSPORT:指定JPDA传输协议,即调试器与虚拟机之间的数据传输方式,默认是dt_socket;
  • JPDA_SUSPEND:指定启动后JVM是否应立即挂起执行,默认为n。

如果需要自定义JPDA,可以在catalina.sh中配置:

JPDA_TRANSPORT=dt_socket
JPDA_ADDRESS=5005
JPAD_SUSPEND=n

或者直接通过JPDA_OPTS参数进行配置:
JPDA_OPTS='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

如果在catalina.sh中配置了以上这些参数,即使不通过jpda start命令启动tomcat,也会开启debug模式。

问题排查

了解了tomcat中是如何开启debug的,那么上面遇到的端口占用问题,也就有了排查的思路。
我首先查看了catalina.sh文件,发现没有配置JPDA的参数,但是tomcat中配置环境变量的文件不止这一个,于是我使用grep搜索了bin目录:

[dev@dev-host tomcat]$ grep -lr  JPDA bin
bin/catalina.bat
bin/catalina.sh

发现确实没有进行JPDA的配置,那么只有可能是通过jpda start默认开启了debug,于是在starup.sh文件末尾找到了这一句exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@" 。而JDPA默认的传输端口8000确实是被另外的java进程占用了:

[dev@dev-host tomcat]$ netstat -apn | grep 8000
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      1 192.168.1.12:35874    100.100.25.95:8080      SYN_SENT    9285/java

那么,可以通过在catalina.sh中配置jpda端口为非8000端口解决该问题,或者直接去掉startup.sh中的jpda,以非debug模式启动tomcat。
案件到此侦破。

你可能感兴趣的:(Java,java,tomcat,jpda,debug)