在IntelliJ IDEA调试Java应用时遇Failed to evaluate breakpoint condition错误的原因与规避
错误含义解析
这个错误直白来说就是:当调试器试图计算你设置的断点条件时,条件中涉及的某个对象已经被JVM的垃圾回收器(GC)回收了,导致调试器无法访问该对象来完成条件判断。
为什么特定代码序列会100%触发?这是因为在那个特定的代码路径下,目标对象的生命周期刚好在断点触发前结束——没有任何强引用再指向它,JVM就会在合适的时机把它回收掉,而调试器要计算条件时,这个对象已经不存在了。删减代码后对象的生命周期被改变(比如多了某个引用或者代码执行顺序变化),所以GC不会回收它,错误也就消失了。
规避方案
结合你的环境(Windows 10、JDK 1.8.0_161、IntelliJ IDEA 2018.1),可以尝试以下几种方法:
调整断点条件,避免直接引用易回收对象
不要在条件中直接使用可能被GC回收的对象,而是提前把需要判断的值用强引用变量存起来。比如原来的条件是user.getAge() == 18,可以在代码中添加一行临时变量:final int targetAge = user.getAge(); // 用强引用变量持有值然后把断点条件改成
targetAge == 18。这样即使user对象被回收,targetAge作为基本类型(或强引用的对象)依然存在,调试器能正常计算条件。修改JVM垃圾回收策略
你当前使用的JDK 8默认垃圾回收器可能在调试时回收过于激进。可以在IDEA的Run/Debug Configurations中,给目标应用的VM options添加参数:-XX:+UseSerialGCSerial GC是单线程回收器,在调试场景下会更保守,不容易回收调试器需要访问的对象。
临时延长对象生命周期
在代码中给目标对象添加一个全局强引用,防止它被GC回收。比如:// 临时添加,调试完成后删除 private static Object keepAliveHolder; // 在目标对象使用后添加: keepAliveHolder = yourTargetObject;这样只要
keepAliveHolder不被置空,对象就不会被回收,断点条件就能正常计算。升级IntelliJ IDEA版本
你使用的2018.1版本比较老旧,JetBrains在后续版本中修复了大量调试器与GC交互的bug。升级到较新的稳定版本(比如2020.3或更高),大概率能解决这个兼容性问题。升级JDK补丁版本
JDK 1.8.0_161是2018年的版本,后续的JDK 8补丁(比如u391)修复了不少JVM调试接口的问题。升级到同大版本的最新补丁,可能会缓解这个错误。
内容的提问来源于stack exchange,提问作者Gili

