POSTS
避免 Intellij IDEA 远程 debug 卡顿的三个技巧
为什么远程 debugger 可能卡顿?
Intellij IDEA 的远程 debugger 使用 jdwp 协议与 JVM 通信。发生在打断点,查看变量内容,执行代码等 debug 操作后面的,实际上是一系列 jdwp 指令。 跨越公网进行远程 debug 时,受限于网络延迟,一个指令从发出到收到响应,可能需要几十毫秒甚至更长时间。虽然 jdwp 协议本身支持异步通信,但部分 debug 操作仍然只能通过一系列同步的 jdwp 指令完成, 连续多个同步指令的延迟叠加在一起,就会导致肉眼可见的 debug 操作的卡顿。
所以,从原理上来说,为了避免操作卡顿,我们应该尽可能减少不必要的 jdwp 指令。
三个技巧
1. 关闭 toString 对象是图和集合类替代视图
在 IDEA 的 debug 配置 “调试器/数据视图/Java” 中,有两个默认开启的功能,”toString() 对象视图”和 “集合类替代视图”。这两个功能方便在 debug 时直接查看对象内容,但代价是需要执行大量 jdwp 指令。 远程 debug 时,为了避免单步执行等操作卡顿,最好关闭这两个功能。

2. 避免在非挂起(suspend)状态查看 threads 面板
IDEA debugger 的 threads 面板能直观地展示出当前 jvm 内每个线程的名称和状态。在渲染这个面板的过程中,IDEA 会向 jvm 发送一个指令获取所有线程 ID,然后为每个线程 ID 发送两个指令获取线程名称和状态。 如果 jvm 内线程较多(几十个足矣),则需要执行的 jdwp 指令非常多。且 threads 面板会在每次线程开始或退出时完全重建,如果 jvm 内线程频繁变动,该面板可能还处于数据收集状态就触发了重新渲染。

所以,为了减少 jdwp 指令数,避免查看 threads 面板是一个不错的选择。 当然,如果 jvm 因为断点等处于挂起(suspend) 状态,几乎不会出现线程开始/退出的事件,线程面板也不需要频繁重建,这时查看线程面板不会处于长时间加载中。
3. 避免在”对表达式求值”中执行循环操作
IDEA debugger 的 “对表达式求值” 可以让我们在 debug 过程中执行一段代码,查看执行结果。但是,如果这段代码中包含循环操作,当循环次数较多时,执行时间可能非常长, 界面一直显示“求值中”,直到用户无法忍受而关闭窗口。

对 jdwp TCP 连接抓包并分析后可以看出,IDEA 在执行这样的循环时,实际上是在一次次地发送指令,执行方法,等待响应,直到循环结束。总的 jdwp 指令数是循环次数的若干倍,具体的倍数取决于循环体内的代码。
所以,为了避免界面卡顿,应该尽量避免在”对表达式求值”中执行循环操作。