Java 关闭重写的finalize()方法中的类IO资源

Java 关闭重写的finalize()方法中的类IO资源,java,garbage-collection,Java,Garbage Collection,如果我有一个使用IO资源的类,例如磁盘平面文件、DB或其他形式的外部资源,那么在GC运行的重写finalize()方法中关闭这些流/连接的利弊是什么?我认为这可以利用现有的jvmgc,减少依赖客户端调用类似closeResources()的类方法以及编写类似意大利面条的try-catch(嵌套try-catch和ifs是我最不喜欢的编程构造)的风险 作为一个具体的例子,我有一个简单的文件读取包装器。该类由字符串filePath构造,它将文件读入列表。我不想在多个地方关闭BufferedReade

如果我有一个使用IO资源的类,例如磁盘平面文件、DB或其他形式的外部资源,那么在GC运行的重写finalize()方法中关闭这些流/连接的利弊是什么?我认为这可以利用现有的jvmgc,减少依赖客户端调用类似closeResources()的类方法以及编写类似意大利面条的try-catch(嵌套try-catch和ifs是我最不喜欢的编程构造)的风险

作为一个具体的例子,我有一个简单的文件读取包装器。该类由
字符串filePath
构造,它将文件读入
列表
。我不想在多个地方关闭
BufferedReader
,比如在打开文件时关闭它(catch子句),但在文件读取良好时也关闭它。我想把它放在一个地方,并确保无论对象何时得到GC,它总是关闭的


这种方法是一种很好的实践,还是我试图在Java范围内为自己提供过高的便利?

这不是一个好主意,因为
finalize()
方法不能保证被调用

当代码使用完资源后,关闭它们更容易、更好

如果不喜欢编写嵌套的try finally块来正确关闭资源,请使用类似于静默关闭资源(或编写自己的简单util方法来静默关闭它们)的方法:


这不是一个好主意,因为不能保证调用
finalize()
方法

当代码使用完资源后,关闭它们更容易、更好

如果不喜欢编写嵌套的try finally块来正确关闭资源,请使用类似于静默关闭资源(或编写自己的简单util方法来静默关闭它们)的方法:


是的,finally block始终是释放资源(如连接、I/O Sreams等)的最佳方法。

是的,finally block始终是释放资源(如连接、I/O Sreams等)的最佳方法。

如果IO资源是实例变量,则应在
finalize()中关闭它
方法

为什么?

  • 因为使用实例变量,您需要它处于打开状态,因为某些方法将重复使用它

  • 如果您在finalize以外的方法中关闭它,那么您正在创建一个
    时间耦合
    ,这意味着类用户需要知道他必须以特定的时间顺序调用特定的方法,即,在B之前调用a等

  • 编辑:


    Java文档指出,垃圾收集器不保证在任何特定时间运行,并且只要对象有任何引用,垃圾收集器就不会运行
    finalize()
    。如果引用仍然存在,那就是内存泄漏,编程错误<当资源不是方法的本地资源时,code>finalize()是最佳选项。如果该资源是某个方法的本地资源,则当IO资源是实例变量时,应在try/cath块的
    末尾关闭该资源,然后在
    finalize()
    方法中关闭该资源

    为什么?

  • 因为使用实例变量,您需要它处于打开状态,因为某些方法将重复使用它

  • 如果您在finalize以外的方法中关闭它,那么您正在创建一个
    时间耦合
    ,这意味着类用户需要知道他必须以特定的时间顺序调用特定的方法,即,在B之前调用a等

  • 编辑:


    Java文档指出,垃圾收集器不保证在任何特定时间运行,并且只要对象有任何引用,垃圾收集器就不会运行
    finalize()
    。如果引用仍然存在,那就是内存泄漏,编程错误<当资源不是方法的本地资源时,code>finalize()
    是最佳选项。如果资源是某个方法的本地资源,那么在
    try/cath block

    imo的
    finally
    末尾关闭它,我会使用google guava,因为它有很多功能,而不是包括所有apache库。使用google guava,您可以使用
    文件
    classimo,我会使用google guava,因为它有很多功能,而不是包括所有apache库。使用google guava,您可以使用
    文件
    classIs
    BufferedReader
    变量作为构造函数、其他方法的局部变量,或者它是一个实例变量?
    BufferedReader
    变量作为构造函数、其他方法的局部变量,或者它是一个实例变量?我说的是重写Object.finalize(),不是try/catch的最后一个块我说的是覆盖Object.finalize(),不是try/catch的最后一个块谢谢您的详细说明。与@matt b冲突的是,您假设finalize()保证执行。我很想了解更多这方面的信息。基本上,它归结起来就是finalize()是否有保证,以及它的可靠性is@foampileJava文档声明垃圾收集器不保证在任何特定时间运行,并且只要存在对对象的引用,就不会运行
    finalize()
    。如果引用仍然存在,那就是内存泄漏,编程错误<当资源不是方法的本地资源时,code>finalize()是最佳选项。如果资源是某个方法的本地资源,则在
    try/cath块的
    finally
    末尾将其关闭
    try/catch/finally
    块不是spagetti代码。相反。它是结构良好的代码。错误代码检查和标记jumpig是spagetti代码<代码>try/catch/finally
    (异常处理)是在
    InputStream stream = ...;
    try {
        ...
    }
    finally {
        IOUtils.closeQuietly(stream);
    }