写点什么

使用 IDEA 远程 Debug 调试(一篇懂所有)

作者:Java你猿哥
  • 2023-04-25
    湖南
  • 本文字数:1969 字

    阅读完需:约 6 分钟

背景

有时候我们需要进行远程的 debug,本文研究如何进行远程 debug,以及使用 IDEA 远程 debug 的过程中的细节。看完可以解决你的一些疑惑。

配置

远程 debug 的服务,以 springboot 微服务为例(springcloud 的应该差不多,我没研究过)。首先,启动 springboot 需要加上特定的参数。

1、IDEA 设置

高低版本的 IDEA 的设置可能界面有点不一样,我用 2020.1.1 的。大致上差不多,自行摸索。

IDEA 打开远程启动的 springboot 应用程序所对应的

1.选择 Edit Configuration



2.如图,点击加号,选择 Remote



3.配置,详细步骤见图



注意:注意端口别被占用。后续这个端口是用来跟远程的 java 进程通信的。

可以注意到:切换不同的 jdk 版本,生成的脚本不一样

选择 jdk1.4,则为

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=50055
复制代码

这就是你为什么搜其他博客,会有这种配置的原因,其实这个配置也是可行的。但更准确应该按照下面 jdk5-8 的配置

选择 jdk 5-8,则为

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50055
复制代码

选择 jdk9 以上,则为

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:50055
复制代码

据说因为 jdk9 变得安全了,远程调试只允许本地,如果要远程,则需要在端口前配置*

2、启动脚本改造

使用第一步得到的 Command line arguments for remote JVM 即可,即-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50055

改造后的启动脚本如下

nohup java \-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50055 \-jar remote-debug-0.0.1-SNAPSHOT.jar &
复制代码

注意在 windows 中用 ^ 来进行换行,例如

java ^-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50055 ^-jar remote-debug-0.0.1-SNAPSHOT.jar
复制代码

说明:

1、端口可随意自己定,未被占用的都行,但是要和 IDEA 里的 remote 中设置的端口一致!其他参数照抄。详细的参数解释可以参照附录或自己搜

2、remote-debug-0.0.1-SNAPSHOT.jar 改成给你自己的 jar 包名字

3、我给的脚本是后台运行的,如不需要后台运行,自行去掉 nohup 和 &

3、启动 springboot,启动 IDEA 里的



IDEA 远程调试的细节

1、细节 1:停在本地断点,关闭程序后会继续执行吗

如果远程调试在自己的断点处停下来了,此时关闭 IDEA 中的项目停止运行,则还会继续运行执行完剩下的逻辑吗?会的,这点比较不容易记住

以下面的代码为例,在第一行停住了。然后 IDEA 中停掉,发现停掉之后控制台还是打印了剩下的日志。



2、细节 2:jar 包代码和本地不一致会怎么样?

IDEA 里的代码如果不和 jar 包的一致,会怎么样。

结论:要保证和远程启动的代码一致。

否则你 debug 的时候的行数会对不上。报错抛异常倒是不会。像这种还是能对得上行数的

比如你调试 test1 方法,test2 方法在 test1 下面,在 test2 里加代码,这样并不影响 test1 中的行号,这种是可以在调试的时候准确反应行号的

3、细节 3:日志打印在哪里?

日志不会打印在 IDEA 的控制台上。即System.out 以及 log.info 还是打印在远程的。

@GetMapping("/test1")public String test1() { System.out.println("第一行"); System.out.println("第二行"); log.info("log 第一行"); log.info("log 第二行");return"ok";}
复制代码

4、细节 4:调试时其他人会不会卡住?

远程调试的时候,打了断点,停住后会不会导致页面的请求卡住。

比如你使用远程调试,别的 QA 在测试这个页面,结果他们看到的结果是怎么样的?会卡住吗?会的,已经实际遇到过这种情况了。

5、细节 5:本地代码修复 bug 远程调用的时候

如果在远程调试过程自己发现了 bug,本地改好后重新启动 IDEA 里的项目,再到页面调用一次,能修复吗?不能,运行的还是远程部署的 jar 中的代码

这个直接击碎了远程页面点一点触发本地代码进行 debug 的梦想。如果可以的话那调试代码就方便太多。

6、细节 6:这个不算远程调试的问题,是 dropframe 的问题,放在这里一起讲了

关于drop frame的问题,如果drop frame了重新进行调试,会不会插入 2 条记录?

如图 userMapper.insert(eo) ,本方法没有使用 @Transactional 修饰,mapper 方法执行过后事务会被立即提交,则库表里多了一行记录,如果drop frame后,再次进行调试,再次执行这代码,于是又插入了一条记录。



如果加上 @Transational 就不会有两条记录了,dropframe 的时候事务没被提交,再次执行该插入代码也不会插入 2 条。

关于什么是 drop frame



7、细节 7:跟上面一样,是 dropframe 问题

如果把上述插入数据库的逻辑,换成调用远程的接口,在 dropframe 后,再次执行相同的代码,会不会导致远程接口被执行了 2 次?会的。

总结

好像感觉远程调试的用处也不是那么大,不能作为长期使用的调试工具。只能作为临时调试的手段。

难点有几个:

  • 难保证本地代码和远程一致,而且你也很难判断是否一致

  • 通过远程调试发现了 bug,但是又不能立即修复后继续调试,只能修复后部署后继续远程调试

用户头像

Java你猿哥

关注

一只在编程路上渐行渐远的程序猿 2023-03-09 加入

关注我,了解更多Java、架构、Spring等知识

评论

发布
暂无评论
使用 IDEA 远程 Debug 调试(一篇懂所有)_Java_Java你猿哥_InfoQ写作社区