资源生命周期与 AutoCloseable
资源所有权与 AutoCloseable:谁创建谁关闭、跨层传递资源时的生命周期纪律。
#type / concept
#status / growing
#tech / dev
#resource / java
[!info] 关联笔记
资源生命周期与 AutoCloseable
这个概念为什么出现
资源泄漏是生产慢性病:连接耗尽、文件句柄打满。技术机制是 close,工程机制是所有权:谁创建,谁负责释放;谁借用,谁按契约归还。
[!abstract] 一句话理解
AutoCloseable标出可关闭资源;生命周期纪律是“所有权清晰 + 异常路径也释放 + 池化资源按池契约归还”。
最小可运行示例
场景:包装一个计数型资源,确保 close 只成功一次
import java.util.concurrent.atomic.AtomicInteger;
final class Lease implements AutoCloseable {
private static final AtomicInteger OPEN = new AtomicInteger();
private boolean closed;
Lease() { OPEN.incrementAndGet(); }
static int openCount() { return OPEN.get(); }
@Override public void close() {
if (!closed) {
closed = true;
OPEN.decrementAndGet();
}
}
}
public class LeaseDemo {
static void use() {
try (Lease lease = new Lease()) {
System.out.println("in-use=" + Lease.openCount());
}
}
public static void main(String[] args) {
use();
System.out.println("after=" + Lease.openCount());
}
}
建议运行:
javac LeaseDemo.java && java LeaseDemo
期望输出:
in-use=1
after=0
结合场景再看三个关注点
- close 应幂等(多次关闭安全)。
- 作用域结束即释放,不要把短生命周期资源塞进长期字段。
- 池化对象的 close 可能是归还,不是物理销毁——读文档。
核心概念与准确模型
1. 所有权转移
| 模式 | 责任 |
|---|---|
| 工厂返回资源 | 文档写清由调用方关闭 |
| 方法内打开 | 方法内 TWR 关闭 |
| 依赖注入单例客户端 | 应用停止时关闭 |
2. Closeable vs AutoCloseable
Closeable继承AutoCloseable,close抛IOException- 更广资源实现
AutoCloseable
3. 与优雅关闭关系
进程退出前要关闭线程池、服务端 socket、数据源——见服务工程。
边界情况与反直觉行为
- 关闭顺序:先依赖方后底层。
- 异步回调持有资源易泄漏。
- 异常构造半对象时注意已获取资源回滚。
常见误区
[!warning] 常见误区:连接池拿来的 Connection 不关闭 必须 close/归还,否则池耗尽。
工程实践
- API 文档写清 ownership。
- 静态分析/实验检测泄漏。
- 超时与取消路径也要释放。
- 测试用计数/代理断言 close 次数。
本节总结
- 资源=所有权问题
- AutoCloseable + TWR 是机制
- 池化与进程级关闭是工程延伸
自测题
- 为什么 close 最好幂等?
- 方法返回 InputStream 时谁关闭?
参考答案
- 防御双重关闭与错误路径重复清理。
- 通常调用方;文档必须明确,否则必泄漏。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| AutoCloseable | API | 契约 |
| Closeable | API | IO 关闭 |