如何解决IntelliJ远程调试Docker中JVM的验证器内部不一致错误?
我之前在远程调试Docker里的Java应用时也碰到过一模一样的“verifier detected internal inconsistency or security problem”错误,结合你给出的环境(IntelliJ IDEA 2018.1.3 EAP + Ubuntu Docker容器内的Java 8u151),整理了几个亲测有效的解决方法:
调整JVM字节码验证参数
Java 8u151开始收紧了字节码验证规则,Hot Swap时生成的修改后字节码很容易触发这个严格验证。你可以给容器内的JVM添加以下启动参数来放宽验证:-XX:-UseSplitVerifier -noverify具体操作可以在Docker启动命令里追加到
JAVA_OPTS,或者在Dockerfile中设置ENV JAVA_OPTS="-XX:-UseSplitVerifier -noverify"。-XX:-UseSplitVerifier会关闭Java 7引入的拆分式验证逻辑,回到更宽松的旧验证模式;-noverify则直接跳过整个字节码验证环节,完全适配调试场景。检查IDEA的Hot Swap配置
打开IDEA的File > Settings,导航到Build, Execution, Deployment > Debugger > HotSwap:- 确保Allow hot swap in remote debug sessions选项已经勾选;
- 把Reload classes after compilation设置为
Prompt或者Always,避免自动重载时的静默冲突; - 另外,尝试关闭Use external build选项(在
Build, Execution, Deployment > Compiler里),有时候外部构建工具会和IDEA的Hot Swap逻辑冲突。
升级Java或IDEA版本
Java 8u151确实存在几个和字节码验证、Hot Swap相关的已知bug,Oracle在后续的小版本(比如u161及以上)中修复了这些问题。如果业务允许,建议把容器内的JRE升级到Java 8u161或更高的8u稳定版本。
同时,你使用的IDEA 2018.1.3是EAP预览版,本身可能存在未修复的Hot Swap兼容性问题,试试升级到同系列的正式版(比如2018.1.6)或者更高版本的IDEA(比如2018.2+),正式版的调试逻辑会更稳定。手动触发Hot Swap替代自动重载
自动Hot Swap有时候会因为编译时机、容器网络延迟等原因出问题,试试手动操作:修改代码后先执行Build > Build Project编译,然后在调试窗口点击Reload Changed Classes按钮(就是那个带箭头的圆形图标),手动触发类重载,看看是否还会触发验证器错误。确认远程调试参数的正确性
确保容器内的JVM启动时配置了正确的远程调试参数:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005注意
address=*:5005是关键,不要写成localhost:5005,否则容器外的IDEA无法连接。同时检查Docker的端口映射规则,确保容器的5005端口已经映射到宿主机的对应端口,IDEA远程调试配置里的主机地址和端口要和映射后的一致。
内容的提问来源于stack exchange,提问作者user674669

