try-with-resources 通过 JVM 编译器在字节码中插入隐式 finally 保障资源关闭,无论 try 块是否异常退出;多资源逆序关闭确保依赖安全;close 异常以 suppressed 形式附加到主异常,不丢失信息。

try-with-resources 能在异常情况下确保资源关闭,核心靠 JVM 编译器层面的保障机制,不是靠程序员手动补救。
资源关闭不依赖 try 块是否成功执行
只要资源在 try 括号中完成声明和初始化(即构造函数没抛异常),JVM 就会在 try 块退出时(无论正常结束、return、break 还是抛出异常)自动调用其 close() 方法。
这意味着:即使 readLine() 抛出 IOException,或业务逻辑 throw new RuntimeException,前面已成功创建的 FileInputStream 和 BufferedReader 仍会被依次关闭。
关闭动作嵌入在字节码的 finally 逻辑里
编译器会把 try-with-resources 翻译成等效的 try-finally 结构。例如:
立即学习“Java免费学习笔记(深入)”;
原始写法:
try (FileInputStream fis = new FileInputStream("a.txt")) { ... }
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
实际等效于(简化示意):
FileInputStream fis = null;
try {
fis = new FileInputStream("a.txt");
...
} finally {
if (fis != null) fis.close();
}
这个隐式 finally 是 JVM 强制插入的,不受 Java 层面异常处理影响。
多资源按逆序关闭,且每个都独立保障
多个资源用分号隔开,关闭顺序与声明相反——这不仅是逻辑优化,更是安全设计:
- 后声明的资源(如 BufferedReader)通常依赖先声明的(如 FileInputStream)
- 逆序关闭保证依赖者先关,被依赖者后关,避免“关了底层流,上层流还试图读”这类错误
- 每个资源的 close() 都有独立的隐式 finally,一个 close 失败不会中断另一个的关闭
异常冲突时用抑制机制保底
如果 try 块抛异常 A,close() 又抛异常 B,B 不会覆盖 A,而是作为 suppressed exception 附加到 A 上。
你仍可通过 e.getSuppressed() 拿到 B,说明 close 确实执行了,只是发生了额外问题。这比传统 finally 中异常吞并更透明、更可靠。

















