30

IntelliJ IDEA远程Debug Linux的Java程序,找问题不要只会看日志了

 3 years ago
source link: https://www.pkslow.com/archives/idea-remote-debug
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1 前言

我们习惯于在本地开发的时候 debug ,能快速定位与解决问题,那部署在服务器上是不是就没有办法了呢?只能通过查看日志来定位?

不是的,在远端的服务器上,我们一样可以 debug

2 IDEA的debug

我们先来看一下在 IntelliJ IDEA 直接 debug 是怎样的。

先准备一个简单的 Java 程序:

package com.pkslow.basic;
import java.util.Map;

public class RemoteDebug {
    public static void main(String[] args) {
        System.out.println("------------------start------------------");
        
        System.out.println("get all the system environment");
        Map<String, String> envs = System.getenv();

        System.out.println("\nprint out the contains `HOME`");
        System.out.println("------env HOME------");
        envs.entrySet().stream()
                .filter(env -> env.getKey().contains("HOME"))
                .forEach(env -> {
                    System.out.println(env.getKey() + ":" + env.getValue());
                });

        System.out.println("------------------end------------------");
    }
}

功能很简单,获取所有系统环境变量,并打印出含有 HOME 字段的。

Debug 很简单,直接点击以下按钮就可以:

EBvAFb.png!mobile

相信大家都知道这一点,但应该很多人都不会注意, IDEA 究竟做了什么,为什么就可以调试了呢?我们看一下控制台的日志就明白了:

/Library/Java/JavaVirtualMachines/jdk1.8.0_212.jdk/Contents/Home/bin/java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:59313,suspend=y,server=n -javaagent:/Users/pkslow/Library/Caches/IntelliJIdea2019.3/captureAgent/debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "/Library/Java/JavaVirtualMachines/jdk1.8.0_212.jdk/Contents/Home/jre/lib/charsets.jar:" com.pkslow.basic.RemoteDebug
Connected to the target VM, address: '127.0.0.1:59313', transport: 'socket'

简化一下,不重要的参数去掉:

java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:59313,suspend=y,server=n com.pkslow.basic.RemoteDebug

这就是可以 Debug 的原因,利用了 Java Agent 原理。这个功能很强大,类似一个 AOP ,代理了 Java 程序,可以利用它进行调试、热部署等。

3 调试本地程序

我们先试试如何可以调试本地程序,不是直接在 IDEA 上调试。先要编译出 class 文件 RemoteDebug.class ,然后按 package 结构放好。我通过 mvn clean compile 来编译。

启动程序,在 target/classes/ 目录执行:

$ java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:50050,suspend=y,server=y com.pkslow.basic.RemoteDebug
Listening for transport dt_socket at address: 50050

然后程序就会等待调试客户端的连接,不会往下执行。

配置 IDEA 以进行调试:

yqYVv2b.png!mobile

配置完成保存后,点击 debug 就可以了:

v267nyv.png!mobile

程序已经进入 debug 模式:

AJ73Evv.png!mobile

我们已经执行到了其中一行,现在看看服务端:

zEjYvun.png!mobile

IDEA 是同步的,并且确实已经控制了服务端 Java 的执行。

4 远程调试Linux Java程序

先把程序部署在 Linux 上:

$ scp -P 22 ./com/pkslow/basic/RemoteDebug.class [email protected]:/root/remoteDebug/com/pkslow/basic/
RemoteDebug.class                              100% 2572   282.5KB/s   00:00

通过以下命令在服务端启动程序,这里调试端口改为 9999 ,因为部分端口在远程服务器并没有开启:

java -agentlib:jdwp=transport=dt_socket,address=9999,suspend=y,server=y com.pkslow.basic.RemoteDebug

本地电脑 IDEA 配置如下:

y2MFfen.png!mobile

开始 debug ,正常控制了远程服务端的 Java

nQNzA3.png!mobile

服务端的实时执行情况:

ZrYNRve.png!mobile

让程序执行完如下:

$ java -agentlib:jdwp=transport=dt_socket,address=9999,suspend=y,server=y com.pkslow.basic.RemoteDebug
Listening for transport dt_socket at address: 9999
------------------start------------------
get all the system environment

print out the contains `HOME`
------env HOME------
JAVA_HOME:/root/jdk1.8.0_131
HOME:/root
------------------end------------------

5 总结

本文一步步探索如何进行调试远程的服务器,这在出现问题时定位还是非常有用的。毕竟可以实时看到服务端运行环境。

欢迎关注微信公众号< 南瓜慢说 >,将持续为你更新...

Y7z2U3.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK