Java7里try-with-resources分析
这个所谓的try-with-resources,是个语法糖。实际上就是自动调用资源的close()函数。和Python里的with语句差不多。
例如:
- static String readFirstLineFromFile(String path) throws IOException {
- try (BufferedReader br = new BufferedReader(new FileReader(path))) {
- return br.readLine();
- }
- }
可以看到try语句多了个括号,而在括号里初始化了一个BufferedReader。
这种在try后面加个括号,再初始化对象的语法就叫try-with-resources。
实际上,相当于下面的代码(其实略有不同,下面会说明):
- static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
- BufferedReader br = new BufferedReader(new FileReader(path));
- try {
- return br.readLine();
- } finally {
- if (br != null) br.close();
- }
- }
很容易可以猜想到,这是编绎器自动在try-with-resources后面增加了判断对象是否为null,如果不为null,则调用close()函数的的字节码。
只有实现了java.lang.AutoCloseable接口,或者java.io.Closable(实际上继随自java.lang.AutoCloseable)接口的对象,才会自动调用其close()函数。
有点不同的是Java.io.Closable要求一实现者保证close函数可以被重复调用。而AutoCloseable的close()函数则不要求是幂等的。具体可以参考Javadoc。
下面从编绎器生成的字节码来分析下,try-with-resources到底是怎样工作的:
- public class TryStudy implements AutoCloseable{
- static void test() throws Exception {
- try(TryStudy tryStudy = new TryStudy()){
- System.out.println(tryStudy);
- }
- }
- @Override
- public void close() throws Exception {
- }
- }
TryStudy实现了AutoCloseable接口,下面来看下test函数的字节码:
- static test()V throws java/lang/Exception
- TRYCATCHBLOCK L0 L1 L2
- TRYCATCHBLOCK L3 L4 L4
- L5
- LINENUMBER 21 L5
- ACONST_NULL
- ASTORE 0
- ACONST_NULL
- ASTORE 1
- L3
- NEW TryStudy
- DUP
- INVOKESPECIAL TryStudy.<init> ()V
- ASTORE 2
- L0
- LINENUMBER 22 L0
- GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
- ALOAD 2
- INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
- L1
- LINENUMBER 23 L1
- ALOAD 2
- IFNULL L6
- ALOAD 2
- INVOKEVIRTUAL TryStudy.close ()V
- GOTO L6
- L2
- FRAME FULL [java/lang/Throwable java/lang/Throwable TryStudy] [java/lang/Throwable]
- ASTORE 0
- ALOAD 2
- IFNULL L7
- ALOAD 2
- INVOKEVIRTUAL TryStudy.close ()V
- L7
- FRAME CHOP 1
- ALOAD 0
- ATHROW
- L4
- FRAME SAME1 java/lang/Throwable
- ASTORE 1
- ALOAD 0
- IFNONNULL L8
- ALOAD 1
- ASTORE 0
- GOTO L9
- L8
- FRAME SAME
- ALOAD 0
- ALOAD 1
- IF_ACMPEQ L9
- ALOAD 0
- ALOAD 1
- INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V
- L9
- FRAME SAME
- ALOAD 0
- ATHROW
- L6
- LINENUMBER 24 L6
- FRAME CHOP 2
- RETURN
- LOCALVARIABLE tryStudy LTryStudy; L0 L7 2
- MAXSTACK = 2
- MAXLOCALS = 3
从字节码里可以看出,的确是有判断tryStudy对象是否为null,如果不是null,则调用close函数进行资源回收。
再仔细分析,可以发现有一个Throwable.addSuppressed的调用,那么这个调用是什么呢?
其实,上面的字节码大概是这个样子的(当然,不完全是这样的,因为汇编的各种灵活的跳转用Java是表达不出来的):
- static void test() throws Exception {
- TryStudy tryStudy = null;
- try{
- tryStudy = new TryStudy();
- System.out.println(tryStudy);
- }catch(Throwable suppressedException) {
- if (tryStudy != null) {
- try {
- tryStudy.close();
- }catch(Throwable e) {
- e.addSuppressed(suppressedException);
- throw e;
- }
- }
- throw suppressedException;
- }
- }
有点晕是吧,其实很简单。使用了try-with-resources语句之后,有可能会出现两个异常,一个是try块里的异常,一个是调用close函数里抛出的异常。
当然,平时我们写代码时,没有关注到。一般都是再抛出close函数里的异常,前面的异常被丢弃了。
如果在调用close函数时出现异常,那么前面的异常就被称为Suppressed Exceptions,因此Throwable还有个addSuppressed函数可以把它们保存起来,当用户捕捉到close里抛出的异常时,就可以调用Throwable.getSuppressed函数来取出close之前的异常了。
总结:
使用try-with-resources的语法可以实现资源的自动回收处理,大大提高了代码的便利性,和mutil catch一样,是个好东东。
用编绎器生成的字节码的角度来看,try-with-resources语法更加高效点。
java.io.Closable接口要求一实现者保证close函数可以被重复调用,而AutoCloseable的close()函数则不要求是幂等的。
Java7里try-with-resources分析的更多相关文章
- 在WebApi项目里使用MiniProfiler并且分析 Entity Framework Core
在WebApi项目里使用MiniProfiler并且分析 Entity Framework Core 一.安装配置MiniProfiler 在现有的ASP.NET Core MVC WebApi 项目 ...
- Java7里try-with-resources分析--转
原文地址:http://blog.csdn.net/hengyunabc/article/details/18459463 这个所谓的try-with-resources,是个语法糖.实际上就是自动调 ...
- php里进程创建和分析
pcntl_fork()函数创建一个子进程,这个子进程仅PID(进程号) 和PPID(父进程号)与其父进程不同成功时,在父进程执行线程内返回产生的子进程的PID,在子进程执行线程内返回0.失败时,在 ...
- spring-mvc里的 <mvc:resources> 及静态资源访问
在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL.配置如下: <servlet> <servlet-name>Sp ...
- springMvc里的mvc:resources与静态资源的访问
在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL.配置如下: <servlet> <servlet-name&g ...
- JQuery里的原型prototype分析
在 JavaScript 中,每个函数对象都有一个默认的属性 prototype,称为函数对象的原型成员,这个属性指向一个对象,称为函数的原型对象,当我们每定义了一个函数的时候,JavaScript ...
- 单例模式中的多线程分析synchronized
谈到单例模式,我们立马会想到饿汉式和懒汉式加载,所谓饿汉式就是在创建类时就创建好了实例,懒汉式在获取实例时才去创建实例,即延迟加载. 饿汉式: 1 package com.bijian.study; ...
- 转:XBMC源代码分析
1:整体结构以及编译方法 XBMC(全称是XBOX Media Center)是一个开源的媒体中心软件.XBMC最初为Xbox而开发,可以运行在Linux.OSX.Windows.Android4.0 ...
- Hadoop源代码分析
http://wenku.baidu.com/link?url=R-QoZXhc918qoO0BX6eXI9_uPU75whF62vFFUBIR-7c5XAYUVxDRX5Rs6QZR9hrBnUdM ...
随机推荐
- SPRING事务的属性有哪些?其中,事务隔离级别有哪几种?什么情况需要使用这几种事务隔离级别?
Spring 声明式事务,propagation属性列表 PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. PROPAGATION_SU ...
- 通向从容之道——Getting things done读书笔记
一.主要的两个目的: 1. 抓住所有一切需要处理的事情: 2. 训练自己在接受一切"输入信息"的前期作出决定. 二.目前的问题: ...
- CSS的应用下
样式继承: 就是父类的颜色如果变了,子类下的div(或者其他属性)会继承父类的. 参考代码: <!DOCTYPE html> <html lang="en"> ...
- Space Golf~物理题目
Description You surely have never heard of this new planet surface exploration scheme, as it is bein ...
- 《Servlet与JSP核心编程》读书笔记
这本书实际是我进入JavaWeb开发的入门书籍,而且是日常碰到一些技术问题需要确认时的参考书,前一段时间在解决一个他人的问题时,我突然发现我的第一遍阅读对这本书的内容的理解还不够透彻,所以又开始N多年 ...
- OkHttp上传文件,服务器端请求解析找不到文件信息的问题
长话短说,不深入解释了,官方给的上传案例代码: private static final String IMGUR_CLIENT_ID = "..."; private stati ...
- mobile angualar ui的简单使用
最近做一个微信App形式的业务平台,之前从别人的推荐文中知道了mobile angualar ui这个东西,这次纯做mobile Web就试用了一下,之前PCWeb中用过AngularJS,Hybri ...
- TabLayout:另一种Tab的实现方式
http://blog.csdn.NET/aigestudio/article/details/47155769 在5.0以前我们想要实现像网易新闻客户端那样的的Tab可以有很多种选择: 比如古老的T ...
- java面试题,附个人理解答案
一,面向对象的特征:1.抽象 包括数据抽象跟行为抽象,将对象共同的特征取出形成一个类2.继承 被继承类为基类/超类,继承类为子类/派生类3.封装 多次使用道德数据或方法,封装成类,方便多次重复调用4. ...
- Spring中IOC和AOP的理解
IOC和AOP是Spring的核心 IOC:控制反转:将创建对象以及维护对象之间的关系由代码交给了spring容器进行管理,也就是创建对象的方式反转了,交由spring容器进行管理. DI:依赖注入: ...
