远程调试Java程序
java 可以以调试模式启动,启动后可以使用 jdb 对程序进行调试。以调试模式启动,需要加入以下参数:
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n
一般如 tomcat, jboss, weblogic 等服务器中会使用 JAVA_OPTS 环境变量,如果要运行这类服务,可以设置该环境变量如下:
linux 下
export JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n" JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"
windows 下
set JAVA_OPTS=%JAVA_OPTS% -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n
maven 使用 MAVEN_OPTS 参数,设置跟上面的类同
以下是一个简单的服务器端代码,接收 UDP 请求
package mm; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UServer { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(8000); while (true) { DatagramPacket dataPackage = new DatagramPacket(new byte[100], 100); socket.receive(dataPackage); System.out.println("Receive from : " + dataPackage.getAddress().getHostName()); System.out.println("Data: [" + new String(dataPackage.getData()) + "]"); dataPackage.setData("abc你好".getBytes()); socket.send(dataPackage); } } }
通过以下命令运行该服务器:
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n mm.UServer
通过以下命运运行 jdb,即可进行调试
[root@server test] # jdb -attach 192.168.1.79:8787 -sourcepath . Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > stop at mm.UServer:12 Set breakpoint mm.UServer:12 > Breakpoint hit: "thread=main", mm.UServer.main(), line=12 bci=11 12 DatagramPacket dataPackage = new DatagramPacket(new byte[100], 100); main[1] next Step completed: "thread=main", mm.UServer.main(), line=13 bci=25 13 socket.receive(dataPackage); main[1] main[1] next > next Nothing suspended. > Step completed: "thread=main", mm.UServer.main(), line=14 bci=30 14 System.out.println("Receive from : " main[1] !! next Step completed: "thread=main", mm.UServer.main(), line=15 bci=42 15 + dataPackage.getAddress().getHostName()); main[1] main[1] !! next > Step completed: "thread=main", mm.UServer.main(), line=14 bci=55 14 System.out.println("Receive from : " main[1] !! next > Step completed: "thread=main", mm.UServer.main(), line=16 bci=58 16 System.out.println("Data: [" + new String(dataPackage.getData()) + "]"); main[1] !! next > Step completed: "thread=main", mm.UServer.main(), line=17 bci=95 17 dataPackage.setData("abc你好".getBytes()); main[1] !! next > Step completed: "thread=main", mm.UServer.main(), line=18 bci=104 18 socket.send(dataPackage); main[1] !! next > Step completed: "thread=main", mm.UServer.main(), line=11 bci=109 11 while (true) { main[1] !! next > Step completed: Breakpoint hit: "thread=main", mm.UServer.main(), line=12 bci=11 12 DatagramPacket dataPackage = new DatagramPacket(new byte[100], 100); main[1]
调试的主要命令有
- stop at 在指定行设置断点
- stop on 在指定的方法设置断点
- next 单步执行到下一步
- !! 重复最后一次命令
目前 eclipse 中已经集成了 jdb,可以在 eclipse 的 debug 选项中设置连接远程主机进行远程调试