使用JAVA远程调用导致程序自动down掉,jdk1.5的debug模式系统漏洞

     在项目上遇到一个系统会突然down掉的问题,因为并没有详细的日志信息,百思不得其解,终于有一天这个问题再次出现,捕获的日志信息为:
ERROR: transport error 202: handshake failed - connection prematurally closed ["transport.c",L41]
JDWP exit error JVMTI_ERROR_NONE(0): could not connect, timeout or fatal error
在网上一查,真相大白,原来是jkd1.5的一个关于debug运行方式的一个bug,原因是由于接收到不符合JDWP协议的数据包,导致JVM崩溃.

问题原因:

该故障是JVM远程debug存在的缺陷,只有在开启远程debug端口时才会出现;原因是由于接收到不符合JDWP协议的数据包,导致JVM崩溃。
要确认系统中是否存在该漏洞,可以检查java启动参数中是否有如下相关配置:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9001
或者-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9001
若存在相关配置,那就说明java启动了远程调试端口,就会存在该漏洞;此时JVM虚拟机作为调试的服务提供端,通过8787端口监听一个连接,而调试器通过该连接与虚拟机进行交互。

 

从官方文档中摘录几个配置事例:
-Xrunjdwp:transport=dt_socket,server=y,address=8000
在8000端口监听Socket连接,挂起VM(suspend默认为y)并且不加载运行主函数直到调试请求到达
-Xrunjdwp:transport=dt_shmem,server=y,suspend=n
选择一个可用的共享内存(因为没有指定address)并监听该内存连接,同时加载运行主函数,不挂起VM
-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

执行,
是可用的共享内存

 

问题解决:

一般线上运行的应用都不会开启远程Debug模式,各应用服务器的默认配置也是不开启的,就算开启了该debug端口也会有防火墙保护。
解决该问题的方法有两种,任选其一即可:
1、在JDK1.5环境下关闭远程调试模式,但线上环境的部署脚本一定要仔细review才行;
2、升级JDK到1.6b49以上版本,这就要看应用的兼容性了,一般来说不会有什么问题;

3、笨方法:不在使用这个方法,哈哈:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9001

4、或者使用如下配置临时代替:-Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false


 

 

你可能感兴趣的:(java开发,Tomcat)