写点什么

Java 中的自动化资源管理

  • 2010-08-25
  • 本文字数:1748 字

    阅读完需:约 6 分钟

Project Coin 的一个突出特点就是具备了自动化资源管理(即 ARM)能力。其目的在于当遇到错误或是成功执行完代码块后能够轻松处理好外部资源。其最初实现位于 OpenJDK 中。考虑如下繁琐的文件拷贝操作,代码来自于 Java Bytestream 教程

复制代码
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c;
while ((c = in.read()) != -1)
out.write(c);
} finally {
if (in != null)
in.close();
if (out != null)
out.close();
}

上面不仅有大量的样版代码,而且 InputStream.close() 的文档表明它会抛出 IOException(OutputStream 也存在类似的异常,无论何种情况,要想成功编译这些代码,要么在外面加上 catch 块,要么将异常继续往外抛)。

try-catch-finally 块的语义范围还要求变量 FileInputStream in 与 FileOutputStream out 声明在块的外面(如果定义在 try 块内,那么 catch 块与 finally 块就访问不到了)。

为了减少上面这些样版代码并且收紧块中所用的资源范围,Java 语言在 try 块中新增了一些内容。最初的 try-with-resources 块(或者叫做 ARM 块)规范已经拥有实现了,随后该规范被纳入到JDK 7 b uild 105 中。

新的接口 java.lang.AutoCloseable 被加到了提案API 中,它只定义了一个会抛出Exception 的方法close()。该接口是 java.io.Closeable 的父接口,这意味着所有的 InputStream 与 OutputStream 都会自动享受到该行为所带来的好处。此外,FileLock 与 ImageInputStream 也实现了 AutoCloseable 接口。

这样,上面的代码就可以这样来写:

复制代码
try (
FileInputStream in = new FileInputStream("xanadu.txt");
FileOutputStream out = new FileOutputStream("outagain.txt")
) {
int c;
while((c=in.read()) != -1 )
out.write();
}

在 try 块的末尾,无论是正常结束还是抛出了异常,out 与 in 资源都会自动调用 close() 方法。此外,与之前示例不同的是 out.close() 与 in.close() 保证会执行(在之前的示例中,一旦 in.close() 方法抛出了异常,随后的 out.close() 方法就没有机会执行了)。

关于这种方式,还有一些微妙之处值得我们注意:

  • 如上代码所示,在资源部分中,最后一个资源后面是不允许使用分号的。
  • 资源块使用 () 分隔,而不是常见的{},以此将其与现有的 try 块分隔开来。如果存在资源块,那么里面必须要包含一个或多个资源定义语句。
  • 每个资源定义具有如下形式:type var = expression; 在资源块中不能使用通常的语句。
  • 资源都是隐式 final 的,也就是说即便没有使用 final,这些资源也都是 final 的。如果尝试为资源变量赋值会得到一个编译期错误。
  • 资源必须是 AutoCloseable 的子类型,如果不是的话会得到一个编译期错误。
  • 资源关闭的顺序与定义的顺序正好相反。换句话说,在上面的代码示例中,out.close() 要先于 in.close() 得到调用。这么做可以构建嵌套的流,然后从外向内关闭流,这要比按顺序关闭更好(也就是说,可以在底层的流关闭前先清空缓存)。
  • 每个块可以生成 n+1 个异常,n 是资源的数量。这出现在代码主体抛出了异常,然后每个资源关闭语句也都抛出异常的情况下。在这种情况下,代码主体的异常将被抛出,但其他的异常将会被添加到异常的抑制列表(suppressed exception list)中。可以通过 getSuppressedExceptions() 方法访问这些异常信息。
  • 异常堆栈追踪信息可以带有 Suppressed 前缀:在这些情况下,序列化的 Throwable 格式也有所不同(如果 Java 6 客户端调用了远程 Java 7 运行时中的服务会出现这个问题,反之亦然)。
  • javax.swing 与 java.sql 目前并不会加入到 ARM 中;类需要继承 AutoCloseable 才能为 ARM 所用。JDBC 4.1 如果能够成为 JDK 7 的一部分,那么它也将支持 ARM,但具体时间尚未确定。

能够移除 Java 开发者每天都要编写的样版代码对生产力的提升是个促进,虽然 JDK 7 具备了这种能力,但有时需要在编写代码前利用这种能力。很多库都需要重新编译以适应 Java 6 的需要,无论何时,只要使用了自动化资源管理,那么它就只能用于使用 -target 7 编译的代码。等到 Java 6 寿终正寝,并且 Java 8 发布后,使用 ARM 就会成为自然而然的事情了。

查看英文原文: Automatic Resource Management in Java

2010-08-25 23:351534
用户头像

发布了 88 篇内容, 共 254.4 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

一文带你学会 Blob(含 7 个使用场景)

pingan8787

Java 大前端 Web Blob

学习总结 - 第 4 周

饶军

架构师训练营作业 -Week4

wyzwlj

极客大学架构师训练营

ARTS-WEEK5

一周思进

ARTS 打卡计划

Prometheus 存储层的演进

伴鱼技术团队

性能优化 系统架构 Prometheus 存储 时序数据库

自由职业的前半年,我是如何度过的?

王磊

Java 程序员

重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程中,配置文件回滚场景」

小傅哥

Java 设计模式 小傅哥 重构 备忘录模式

Linux系统查询端口命令

打鱼小王子

原来使用Postman如此简单,API测试之Postman使用全指南

软测小生

接口 Postman 接口测试 API API测试

央行数字货币:第三方支付产业新变量

CECBC

数字货币 DCEP 区块链技术

小师妹学JVM之:JIT中的PrintAssembly

程序那些事

JVM 小师妹 性能调优 JIT 签约计划第二季

python中对字典与列表组合进行排序

开心太平洋

Python List 排序

GO语言泛型编程实践

老胡爱分享

泛型 Go 语言

围绕 Office 365 的那些 CLI

手艺人杨柳

Office 365

消息队列(三)如何保证消息不被重复消费?

奈何花开

Java MQ 消息队列

CECBC带你一图看懂区块链

CECBC

CECBC 区块链技术 去中心化

架构师训练营 - 第四周命题作业

牛牛

极客大学架构师训练营 作业

万字长文,让 Java 程序员入门小众语言 Ruby

Phoenix

Java ruby 个人成长 编程语言

系统架构感想

朱月俊

《架构师训练营》第四周命题作业

谈反应式编程在服务端中的应用,数据库操作优化,提速 Upsert

newbe36524

C# MySQL 数据库 mongodb Reactive

架构师训练营 - 学习笔记 - 第四周

心在飞

极客大学架构师训练营

安畅迁移平台的云原生之路

雪雷

Kubernetes DevOps 云原生 CI/CD 迁移

计算机操作系统基础(六)---作业管理之进程调度

书旅

Java php 多线程 操作系统 进程

《架构师训练营》第四周总结

架构师训练营第四周学习总结

CATTY

互联网系统常见问题以及解决方案

而立

极客大学架构师训练营

第四周作业

技术小生

极客大学架构师训练营

一个典型的大型互联网应用系统使用了哪些技术方案和手段,主要解决什么问题?

朱月俊

快来解锁Pepper机器人新技能,够酷Pepper就跟你回家!

阿甜

编程 开发者 App 开发 机器人

MyBatis标签trim,你不会以为我是去空格的吧?

Java小咖秀

Java 面试 mybatis

  • 扫码加入 InfoQ 开发者交流群
Java中的自动化资源管理_Java_Alex Blewitt_InfoQ精选文章