为何这段Java代码抛出IllegalArgumentException: Self-suppression not permitted?
问题:try-with-resources抛出Self-suppression not permitted异常
测试代码
public class Test { public static void main(String[] args) { try { doSomething(); } catch (Throwable t) { System.out.println("Caught exception: " + t); } } private static void doSomething() { try ( Resource r = new Resource(); ) { throw new SecurityException("deliberate exception"); } } } class Resource implements AutoCloseable { public void close() { System.out.println("close()"); } }
问题详情
预期输出SecurityException: deliberate exception,但实际得到IllegalArgumentException: Self-suppression not permitted。按常理这个异常只会在try块抛异常后,close()方法也抛出异常时才会出现,但本代码中close()仅打印日志,并未抛出任何异常。虽然可以通过getCause()获取真实异常,但希望搞清楚触发这个行为的原因。
使用环境:OpenJDK 17.0.7(2023-04-18),在VSCode中运行,怀疑是VSCode关联的JVM存在Bug,后续会更换纯javac+java环境测试。
补充:无论抛出受检还是非受检异常,都会出现该Self-suppression问题,选用SecurityException只是为了说明区分异常类型的重要性。
堆栈跟踪
java.lang.IllegalArgumentException: Self-suppression not permitted at java.base/java.lang.Throwable.addSuppressed(Throwable.java:1072) at jLib.Test.doSomething(Test.java:19) at jLib.Test.main(Test.java:7) Caused by: java.lang.SecurityException: deliberate exception at jLib.Test.doSomething(Test.java:18) ... 1 more
分析与建议
Self-suppression not permitted异常是Throwable.addSuppressed()方法抛出的,触发条件是尝试将一个异常作为自身的抑制异常添加。正常的try-with-resources逻辑中,只有当try块抛出异常,同时close()方法也抛出异常时,close的异常才会被添加为try块异常的抑制异常。
但你的代码中close()并未抛异常,却出现这个问题,大概率是VSCode的Java运行环境(比如调试插件、编译工具链)对异常处理做了额外干预,导致JVM在处理抑制异常逻辑时出现了自我添加的错误。
建议:
- 更换纯命令行环境,用
javac Test.java编译后,再用java Test运行,排除IDE插件的影响; - 检查VSCode的Java插件版本,查看是否有已知的相关Bug;
- 可以尝试在try-with-resources块内手动捕获异常并重新抛出,看是否能规避该问题:
private static void doSomething() { try (Resource r = new Resource(); ) { throw new SecurityException("deliberate exception"); } catch (SecurityException e) { throw e; } }
内容的提问来源于stack exchange,提问作者freeideas
相关产品推荐
相关产品推荐

