JAVA
使用TWR优雅关闭物理资源
  • By刘立博
  • 2021-06-14 22:04:38
  • 681人已阅读

常见需手动释放的物理资源

 

文件、流资源

套接字资源

数据库连接资源

 

不释放物理资源的后果

 

对资源无效占用

超过操作系统最大限制后,无法打开新的物理资源

导致系统无法正常运行

 

一个栗子

 

传统方法实现文件拷贝

实例化输入流和输出流,完成相关业务操作后,在finally块中完成物理资源的释放

    public void copyFile()
    {
        String sourceUrl = "";
        String targetUrl = "";

        FileInputStream sourceFileInputStream = null;
        FileOutputStream targetFileOutputStream = null;

        try{
            sourceFileInputStream = new FileInputStream(sourceUrl);

            targetFileOutputStream = new FileOutputStream(targetUrl);

            int read;
            while ( (read = sourceFileInputStream.read()) != -1)
            {
                targetFileOutputStream.write(read);
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if(sourceFileInputStream != null)
            {
                try {
                    sourceFileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if(targetFileOutputStream != null)
            {
                try {
                    targetFileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

使用TWR方式

在try代码块中进行输入流和输出流的实例化操作,JDK会自动释放物理资源

    public void copyFileNew()
    {
        String sourceUrl = "";
        String targetUrl = "";

        try(
                FileInputStream sourceFileInputStream = new FileInputStream(sourceUrl);
                FileOutputStream targetFileOutputStream = new FileOutputStream(targetUrl)
                )
        {
            int read;
            while ( (read = sourceFileInputStream.read()) != -1)
            {
                targetFileOutputStream.write(read);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

原理

JDK是如何实现物理资源释放的呢?使用反编译工具查看编译后的代码可知:所谓的TWR类似C语言的宏,编译器在编译时,会基于try括号中的物理资源声明,自动生成finally代码块,完成资源释放

    public void copyFileNew() {
        String sourceUrl = "";
        String targetUrl = "";

        try {
            FileInputStream sourceFileInputStream = new FileInputStream(sourceUrl);

            try {
                FileOutputStream targetFileOutputStream = new FileOutputStream(targetUrl);

                int read;
                try {
                    while((read = sourceFileInputStream.read()) != -1) {
                        targetFileOutputStream.write(read);
                    }
                } catch (Throwable var9) {
                    try {
                        targetFileOutputStream.close();
                    } catch (Throwable var8) {
                        var9.addSuppressed(var8);
                    }

                    throw var9;
                }

                targetFileOutputStream.close();
            } catch (Throwable var10) {
                try {
                    sourceFileInputStream.close();
                } catch (Throwable var7) {
                    var10.addSuppressed(var7);
                }

                throw var10;
            }

            sourceFileInputStream.close();
        } catch (Exception var11) {
            var11.printStackTrace();
        }

    }