使用 IDEA 远程 Debug 调试,太实用了!
背景
有时候我们需要进行远程的 debug,本文研究如何进行远程 debug,以及使用 IDEA 远程 debug 的过程中的细节。看完可以解决你的一些疑惑。
配置
远程 debug 的服务,以 springboot 微服务为例(springcloud 的应该差不多,我没研究过)。首先,启动 springboot 需要加上特定的参数。
推荐一个开源免费的 Spring Boot 实战项目:
https://github.com/javastacks/spring-boot-best-practice
1、IDEA 设置
高低版本的 IDEA 的设置可能界面有点不一样,我用 2020.1.1 的。大致上差不多,自行摸索。
IDEA 打开远程启动的 springboot 应用程序所对应的
1.选择 Edit Configuration
2.如图,点击加号,选择 Remote
3.配置,详细步骤见图
注意:注意端口别被占用。后续这个端口是用来跟远程的 java 进程通信的。
可以注意到:切换不同的 jdk 版本,生成的脚本不一样
选择 jdk1.4,则为
这就是你为什么搜其他博客,会有这种配置的原因,其实这个配置也是可行的。但更准确应该按照下面 jdk5-8 的配置
选择 jdk 5-8,则为
选择 jdk9 以上,则为
据说因为 jdk9 变得安全了,远程调试只允许本地,如果要远程,则需要在端口前配置*
。
另外,关注公众号 Java 技术栈,在后台回复关键字:IDEA,阅读我写的大量 IDEA 教程。
2、启动脚本改造
使用第一步得到的 Command line arguments for remote JVM
即可,即-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50055
改造后的启动脚本如下
注意在 windows 中用 ^ 来进行换行,例如
说明:
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
还是打印在远程的。
4、细节 4:调试时其他人会不会卡住?
远程调试的时候,打了断点,停住后会不会导致页面的请求卡住。
比如你使用远程调试,别的 QA 在测试这个页面,结果他们看到的结果是怎么样的?会卡住吗?会的,已经实际遇到过这种情况了。
5、细节 5:本地代码修复 bug 远程调用的时候
如果在远程调试过程自己发现了 bug,本地改好后重新启动 IDEA 里的项目,再到页面调用一次,能修复吗?不能,运行的还是远程部署的 jar 中的代码
这个直接击碎了远程页面点一点触发本地代码进行 debug 的梦想。如果可以的话那调试代码就方便太多。
另外,如果你近期准备面试跳槽,建议在Java面试库小程序在线刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。
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,但是又不能立即修复后继续调试,只能修复后部署后继续远程调试
评论