Java 关闭重写的finalize()方法中的类IO资源
如果我有一个使用IO资源的类,例如磁盘平面文件、DB或其他形式的外部资源,那么在GC运行的重写finalize()方法中关闭这些流/连接的利弊是什么?我认为这可以利用现有的jvmgc,减少依赖客户端调用类似closeResources()的类方法以及编写类似意大利面条的try-catch(嵌套try-catch和ifs是我最不喜欢的编程构造)的风险 作为一个具体的例子,我有一个简单的文件读取包装器。该类由Java 关闭重写的finalize()方法中的类IO资源,java,garbage-collection,Java,Garbage Collection,如果我有一个使用IO资源的类,例如磁盘平面文件、DB或其他形式的外部资源,那么在GC运行的重写finalize()方法中关闭这些流/连接的利弊是什么?我认为这可以利用现有的jvmgc,减少依赖客户端调用类似closeResources()的类方法以及编写类似意大利面条的try-catch(嵌套try-catch和ifs是我最不喜欢的编程构造)的风险 作为一个具体的例子,我有一个简单的文件读取包装器。该类由字符串filePath构造,它将文件读入列表。我不想在多个地方关闭BufferedReade
字符串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()中关闭它
方法
为什么?
时间耦合
,这意味着类用户需要知道他必须以特定的时间顺序调用特定的方法,即,在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,您可以使用文件
classIsBufferedReader
变量作为构造函数、其他方法的局部变量,或者它是一个实例变量?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);
}