Java 远程 debug

本地 Debug 很容易, 那么远程 debug 是怎么做的, 又有哪些坑呢?

一般应用程序 debug

这里的一般应用程序就是一个 main 函数, 不是 web 应用程序. 首先, 这个应用在远程某主机上能运行, 只要启动的时候, 添加远程 debug 参数就可以了.

比如有如下代码, 为了让它慢一点可以 debug, 加入了一个循环和睡眠:

public class Debugger {
    
    public int loop(int count) {
        int sum = 0;
        for (int i = 0; i < count; i++) {
            sum += i;
            try {
                System.out.println(i + "/" + count + " current sum: " + sum);
                Thread.sleep(5L);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return sum;
    }
    
    public static void main(String[] args) {
        Debugger debugger = new Debugger();
        int sum = debugger.loop(10000);
        System.out.println("sum is " + sum);
    }

}

在远程编译, 启动, 并且加入监听端口为了方便远程debug:

$ javac Debugger.java
$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000 Debugger 

这里注意的是, 我们对于地址使用的是: 0.0.0.0:8000, 有些地方你看到的直接是 8000 端口, 没有主机ip部分. 这会导致这个端口只是开在 localhost, 你如果使用 netstat 查看, 能看到 8000 端口是开着的, 但是远程无法连接.
在远程可以使用 telnet 或者 curl 来测试这个端口是不是可以远程连接. 但是注意这个端口只能有一个远端能连接成功, 假如你已经使用 curl 连接上, 那么你远端的其它 IDE 就不能连接了.

我本地的 Eclipse 连接的过程是: 在菜单 Run 里面选择 Debug Configurations, 然后新建 Remote Java Application, 然后输入远程的 IP 和 端口. 如下:
remote_debug.png

连接后, Eclipse 会显示连接成功, 然后点击 暂停, 就会暂停远程的应用了.
debug_pause.png

debug 远程 tomcat 里面的应用

在 Tomcat 的 catalina.sh 里面, 添加如下环境变量设置:

export JPDA_ADDRESS=0.0.0.0:8000
export JPDA_TRANSPORT=dt_socket

然后启动时候, 添加 jdpa 参数, 就可以了

./catalina.sh jpda start

debug 远程基于 Spring boot 的应用

其实 Spring boot 是做的 fat jar, 它的远程debug 方式跟一般的应用是一样的, 就是在启动参数里面加上. 例子如下:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000 -jar myApp.jar 

隧道技术

有时候远程机器隔着防火墙, 你不能直接连, 但是你可以通过 ssh 登录, 那么就可以用过隧道技术, 使用 ssh 做隧道, 然后远程 debug.
首先, 我们假设远程机器的 debug 开在 8000 端口上:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000 -jar myApp.jar 

然后在本地机器上建立隧道:

ssh -L 5000:localhost:8000 user@remote_ip

这里的意思是: 在本地启动5000端口, 它所有的数据原封不动的转到远程 remote_ip 的8000 端口. 我们登录远程 remote_ip 的用户名是 user, 这里它会让你输入 ssh user 的密码. 连接成功后, 隧道建立.

这时候, 在本地和之前的一样, 只是把远程机器的ip 改成本地机器localhost, 端口改成 5000. 就能借助隧道进行远程 debug 了.

标签: none

添加新评论