在try-with-resources中,若try块和资源close()均抛异常,则close()异常被抑制并添加到主异常中,可通过getSuppressed()获取 suppressed 异常数组。

在 try-with-resources 语句中,如果 try 块抛出异常,同时资源关闭(即调用 close())也抛出异常,Java 会将关闭时的异常“抑制”(suppressed),并将其附加到主异常上。你可以通过 Throwable.getSuppressed() 方法获取这些被抑制的异常。
被抑制异常出现的典型场景
当以下两个条件同时满足时,就会产生被抑制异常:
- try 块中主动抛出了一个异常(比如
IOException); - 某个实现了
AutoCloseable的资源在自动关闭过程中也抛出了异常(比如另一个IOException或RuntimeException)。
此时,try 块抛出的异常成为“主异常”,而 close() 抛出的异常会被压制,并通过 addSuppressed() 添加到主异常中。
如何用 getSuppressed() 查看被抑制的异常
调用 getSuppressed() 返回一个 Throwable[] 数组,每个元素就是一个被抑制的异常。你需要在捕获主异常后显式访问它:
立即学习“Java免费学习笔记(深入)”;
try (FileInputStream fis = new FileInputStream("test.txt");
FileOutputStream fos = new FileOutputStream("out.txt")) {
// 可能抛出 IOException
throw new IOException("读取失败");
} catch (IOException e) {
System.out.println("主异常: " + e.getMessage());
Throwable[] suppressed = e.getSuppressed();
if (suppressed.length > 0) {
System.out.println("被抑制的异常共 " + suppressed.length + " 个:");
for (int i = 0; i < suppressed.length; i++) {
System.out.println(" [" + i + "] " + suppressed[i]);
}
}
}
注意:只有主异常对象(即 catch 到的那个)才可能包含被抑制异常;被抑制异常自身不会继续压制其他异常。
哪些资源会触发抑制机制
只要资源类型实现了 AutoCloseable(包括 Closeable),且其 close() 方法抛出异常,就可能被抑制。常见例子包括:
-
FileInputStream/FileOutputStream(close()可能抛IOException) - 自定义类实现
AutoCloseable并在close()中 throw 异常 - 数据库连接(如
Connection、Statement)的close()方法
但要注意:如果 close() 没有抛异常,就不会有被抑制异常;如果 try 块没抛异常,即使 close() 抛了,它也会作为主异常被抛出,不被抑制。
调试和日志中的实用建议
在生产环境或调试中,容易忽略被抑制异常,导致问题排查不完整。建议:
- 日志框架(如 SLF4J、Log4j2)默认不会打印被抑制异常,需手动扩展日志内容
- 使用
ExceptionUtils.getStackTrace(e)(Apache Commons Lang)可自动包含 suppressed 异常堆栈 - IDE 调试时,在异常变量上右键 → “View Stack Trace” 通常会显示 suppressed 部分(IntelliJ 和 Eclipse 均支持)
不复杂但容易忽略。


















