6

Java 没有对象的生命周期,这是由garbage collector. 如果我使用一些 IO 类而不关闭它,或者一些DBConnection,这会被认为是资源泄漏吗?换句话说,IO对象是否会被垃圾收集器AFAIK收集和销毁,垃圾收集器仅用于内存。例如:

BufferedReader br = new BufferedReader( new FileReader( new File("path") ) );
4

3 回答 3

8

是的你是对的。

垃圾收集释放 Java 堆(内存),但 close() 释放用于打开文件的操作系统资源(在大多数系统上打开文件的数量是有限的)并确保数据确实被写入。

但是许多类(例如FileInputStreamRandomAccessFile)都是用 finalize() 方法编写的,该方法确保如果垃圾收集中的实例,close() 将首先被调用。所以在很多情况下,垃圾回收确实会间接释放文件,而且程序员经常可能会懒于关闭资源,因为垃圾回收通常会为你清理它们。很遗憾。

问题是您无法控制何时发生这种情况,而且它可能根本不会发生。因此,如果您打开了太多文件,操作系统可能会在垃圾收集器开始关闭它们之前给您一个错误。或者,如果您想移动或删除文件,请在读取文件后立即 - 移动或删除可能会失败,因为此时您仍然可以打开文件以供阅读。

像这样的错误通常很难可靠地重现,因为它们取决于垃圾收集器的时间。所以你得到的东西通常可以正常工作,但有时会神秘地失败。调试起来很烦。出于这个原因,强烈建议您在完成后立即关闭()您可能正在使用的任何流/读取器/连接或其他可关闭资源。最好在 finally 块中,以确保即使在处理过程中发生一些其他错误也会发生。

在 Java 7 中,增加了AutoClosable接口,请在此处了解更多信息。

参考: http: //www.coderanch.com/t/278165//java/InputStream-close-garbage-collection

于 2013-08-29T11:45:25.047 回答
1

“Java 没有对象的生命周期,这是由垃圾收集器管理的。” - 不完全正确。它首先是通过编写程序的方式来“管理”的。如果一个对象超出范围,GC 很可能会处理它。

如果你不关闭br,它将一直存在到程序退出,除非准备好收集时被 GC 收集。它不会泄漏,只是一个长期存在的变量。

于 2013-08-29T11:45:21.233 回答
1
And if I use some IO classes without closing it, or some DBConnection, will
this considered a resource leak?

说使用相同的 IO 类是错误的术语。如果您创建一个资源/连接,然后将其用于其他资源的引用而没有实际关闭原始资源,那么如果没有对原始资源的活动引用,那么它将有资格进行 GC。

但是,在原始资源被 GC 之前,所有操作系统资源(文件句柄等)都不会被释放。当对象将受到 GC(在该对象/资源上调用 finalize() 方法)时,首先调用 close(),因为释放了与操作系统相关的资源,然后是堆内存。

例如考虑 FileInputStream finalize() 方法如下

protected void finalize() throws IOException {
    if ((fd != null) &&  (fd != FileDescriptor.in)) {

        /*
         * Finalizer should not release the FileDescriptor if another
         * stream is still using it. If the user directly invokes
         * close() then the FileDescriptor is also released.
         */
        runningFinalize.set(Boolean.TRUE);
        try {
            close();
        } finally {
            runningFinalize.set(Boolean.FALSE);
        }
    }
}

您会看到首先调用 close()。

因此,尽管 GC 会为您处理内存管理,但在您不需要时在 finally 语句中关闭资源是一种很好的编程习惯。

于 2013-08-29T11:54:27.540 回答