unclosed流是否导致java中的内存泄漏?

Buz*_*ear 13 java memory-leaks memory-management

我相信开放流会导致java中的内存泄漏(至少java 1.6及更早版本确实存在这个问题).

但是,在搜索时(即使在这里),我发现有些人同意这一点,而其他人却没有.所以,如果我写这个程序:

import java.io.*;
public class CreatingMemoryLeak {

    public static void main(String args[])
    {
        String s = "xxxxxxx";
        InputStream in = new ByteArrayInputStream(ss.getBytes());
        BufferedInputStream bf = new BufferedInputStream(in);

        try {
            while(bf.read()>0)
            {
                System.out.println("got it");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Here is a input stream " + s +" causing a memory leak");

    }
}
Run Code Online (Sandbox Code Playgroud)

如果我没有bf明确关闭流,它会导致内存泄漏吗?

bma*_*ies 33

准确地使用与Java相关的术语"内存泄漏"非常重要.

在Java中,当您的代码永久保存引用时会发生内存泄漏,因此某些对象永远不会被垃圾回收.

在这种意义上,未能关闭流不是内存泄漏.具有本机资源的流具有终结器; GC最终将关闭它们.除非你持有对未封闭流的引用,否则它不是泄漏.

但是,除了内存泄漏之外还有其他类型的泄漏.大多数操作系统限制打开文件的数量.如果您未能关闭流,GC可能需要很长时间才能关闭它们; 最终结果可能是您用完了系统文件描述符,而您的代码无法再打开一个文件.有些人会称之为泄漏,但将其称为内存泄漏并不准确.

  • +1 - 这是资源泄漏,而不是内存泄漏. (9认同)

fge*_*fge 6

(至少java 1.6及更早版本确实存在这个问题).

任何版本的Java,就此而言,任何语言都有这个问题; 它不是特定于Java.

如果您掌握了需要系统资源的输入或输出句柄,则无论如何都需要释放它们.

Java必须Closeable表明您拥有的实例可能拥有或拥有系统资源; 但如果不这样做.close(),你就会泄漏资源; 就这么简单.

例如,您可能有一个具有InputStream参数的方法; 好的,很好,但这是什么InputStream?是一个FileInputStream还是一个ByteArrayInputStream,甚至是别的什么?你无法知道.第一个需要正确关闭,但第二个不需要.

所以呢?.close()无论如何,他们都没有什么可失去的.你真的想抓住这个机会吗?

使用Java 6,您将需要使用Guava Closer,因为这是关闭所有资源的最安全的方法(并且JDK不提供这样的工具):

final Closer closer = Closer.create();

try {
    final InputStream in = closer.register(openInHere());
    final InputStream in2 = closer.register(...);
    final OutputStream out = closer.register(...);
    // do work with in, in2, out, other
} catch (WhateverException e) {
    // IF WhateverException is not an IOException and you want to rethrow...
    // throw closer.rethrow(e, WhateverException.class);
} finally {
    closer.close(); // always safe
}
Run Code Online (Sandbox Code Playgroud)

使用Java 7,您可以使用try-with-resources来处理所有AutoCloseable资源(Closeable扩展):

try (
    final InputStream in = ...;
    // etc
) {
    // work with AutoCloseable resources
} catch (WhateverException e) {
    // deal with e, rethrow if necessary
}
Run Code Online (Sandbox Code Playgroud)

Closer和资源尝试之间的主要区别在于,对于后者,资源将被关闭, catchCloser将关闭它们finally.

但同样:不要冒险.关闭它们.