zoukankan      html  css  js  c++  java
  • Java正常关闭资源的方式

    在实际开发中,经常需要在程序中打开一些物理资源,如数据库连接、网络连接、磁盘文件等,打开这些物理资源之后必须显式关闭,否则将会引起资源泄漏。

    JVM的垃圾回收机制不会回收这些资源,垃圾回收机制属于Java内存管理的一部分,它只是负责回收堆内存中分配出来的内存,至于程序中打开的物理资源,垃圾回收机制是无能为力的。

    为了正常关闭程序中打开的物理资源,应该使用finally块来保证回收。

    下面程序示范了常见的数据库资源。

    importjava.sql.Connection;

    importjava.sql.DriverManager;

    importjava.sql.PreparedStatement;

    importjava.sql.ResultSet;

    importjava.sql.SQLException;

    public class Tester {

      public static void main(String[] args) {

          String url = "jdbc:mysql://localhost:3306/test";

          String user = "root";

          String password = "root";

          Connection conn = null;

          PreparedStatement pst = null;

          ResultSet rs = null;

          try {

             Class.forName("com.mysql.jdbc.Driver");

             conn = DriverManager.getConnection(url,user, password);

             pst = conn.prepareStatement("select* from test");

             rs = pst.executeQuery();

             while (rs.next()) {

                 System.out.println(rs.getObject(0));

             }

          } catch (ClassNotFoundException e) {

             e.printStackTrace();

          } catch (SQLException e) {

             e.printStackTrace();

          } finally {

             try {

                rs.close();

                pst.close();

                conn.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

          }

      }

    }

    虽然程序已经使用finally块来保证资源被关闭,但是这个程序的关闭是不安全的。因为程序开始时指定conn = null;pst = null;rs = null;,完全有可能在程序运行过程中初始化conn之前就引发了异常,那么conn、pst、rs还未来得及初始化,因此它们根本无需关闭。

    将上面程序改为如下形式:

    importjava.sql.Connection;

    importjava.sql.DriverManager;

    importjava.sql.PreparedStatement;

    importjava.sql.ResultSet;

    importjava.sql.SQLException;

    public class Tester {

      public static void main(String[] args) {

          String url = "jdbc:mysql://localhost:3306/test";

          String user = "root";

          String password = "root";

          Connection conn = null;

          PreparedStatement pst = null;

          ResultSet rs = null;

          try {

             Class.forName("com.mysql.jdbc.Driver");

             conn = DriverManager.getConnection(url,user, password);

             pst = conn.prepareStatement("select* from test");

             rs = pst.executeQuery();

             while (rs.next()) {

                 System.out.println(rs.getObject(0));

             }

          } catch (ClassNotFoundException e) {

             e.printStackTrace();

          } catch (SQLException e) {

             e.printStackTrace();

          } finally {

             try {

                if(rs != null){

                   rs.close();

                }

                

                if(pst != null){

                   pst.close();

                }

                

                if(conn != null){

                   conn.close();

                }

            } catch (SQLException e) {

                e.printStackTrace();

            }

          }

      }

    }

    程序首先保存rs不为null才关闭,再保证pst不为null才关闭pst,再保证conn不为null才关闭conn。

    这样表面看起来安全,实际上并不是这样。假如程序开始已经正常初始化了conn、pst、rs,在关闭rs时出现了异常,那么程序将在关闭rs时非正常退出,这样就会导致pst、conn得不到关闭,从而导致资源泄漏。

    为了保证关闭各资源时出现的异常不会相互影响,应该在关闭每个资源时分开使用try...catch块来保证关闭操作不会导致程序非正常退出。

    importjava.sql.Connection;

    importjava.sql.DriverManager;

    importjava.sql.PreparedStatement;

    importjava.sql.ResultSet;

    importjava.sql.SQLException;

    public class Tester {

      public static void main(String[] args) {

          String url = "jdbc:mysql://localhost:3306/test";

          String user = "root";

          String password = "root";

          Connection conn = null;

          PreparedStatement pst = null;

          ResultSet rs = null;

          try {

             Class.forName("com.mysql.jdbc.Driver");

             conn = DriverManager.getConnection(url,user, password);

             pst = conn.prepareStatement("select* from test");

             rs = pst.executeQuery();

              while(rs.next()) {

                 System.out.println(rs.getObject(0));

             }

          } catch (ClassNotFoundException e) {

             e.printStackTrace();

          } catch (SQLException e) {

             e.printStackTrace();

          } finally {

             if (rs != null) {

                try {

                   rs.close();

                } catch (SQLException e) {

                   e.printStackTrace();

                }

            }

            if (pst != null) {

                try {

                   pst.close();

                } catch (SQLException e) {

                   e.printStackTrace();

                }

            }

            if (conn != null) {

                try {

                   conn.close();

                } catch (SQLException e) {

                   e.printStackTrace();

                }

            }

          }

      }

    }

    上面程序所示的资源关闭方式才是比较安全的,这种关闭方式主要保证如下3点:

    1. 使用finally块来关闭物理资源,保证关闭操作总是会被执行;

    2. 关闭每个资源之前首先保证引用该资源的引用变量不为null;

    3. 为每个物理资源使用单独try...catch块关闭资源,保证关闭资源时引发的异常不会影响其他资源的关闭。

     转载:http://blog.csdn.net/leaderman_it/article/details/7445491
     
  • 相关阅读:
    AutoCAD 2012安装错误,与.net framework (1603错误)以及ms2005vc++的问题。
    [转载]Thrift的C#入门Demo_图文详解版
    ASPX的Timer位置没放正确,导致整页刷新,而不是UpdatePanel里的内容刷新。
    div、ul、li等无法居中问题,text-align无效 margin auto无效
    flash导入图片缩放后出现毛边、失真、锯齿、文字模糊不清晰的情况
    table居中方法之一:设置width,然后为style设置margin:auto
    ZR普转提day1
    从“四人过桥”到“N人过桥”
    Luogu P2375 [NOI2014]动物园
    Luogu P3435 [POI2006]OKR-Periods of Words
  • 原文地址:https://www.cnblogs.com/ziq711/p/5376455.html
Copyright © 2011-2022 走看看