未关闭的流是否会导致 Java 中的内存泄漏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22889075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Do unclosed streams cause memory leaks in java?
提问by BuzzLightYear
I believe open streams cause memory leak in java (at least java 1.6 and earlier did had this problem).
我相信开放流会导致 java 中的内存泄漏(至少 java 1.6 及更早版本确实有这个问题)。
But, while searching (even here), I found some people agreeing with this while others do not. So, if I write this program:
但是,在搜索时(甚至在这里),我发现有些人同意这一点,而其他人则不同意。所以,如果我写这个程序:
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");
}
}
and if I do not close the bf
stream explicitly, will it cause a memory leak?
如果我没有bf
明确关闭流,它会导致内存泄漏吗?
回答by fge
(at least java 1.6 and earlier did had this problem).
(至少 java 1.6 及更早版本确实有这个问题)。
ANY version of Java, and for that matter, ANY language, has this problem; it is not specific to Java.
任何版本的 Java,就此而言,任何语言都有这个问题;它不是特定于 Java 的。
If you get hold of an input or output handle which needs system resources, you need to release them no matter what.
如果您掌握了需要系统资源的输入或输出句柄,则无论如何都需要释放它们。
Java has Closeable
to signify that the instance you hold may, or may not, hold system resources; but in the event that it does, if you don't .close()
it you'll leak resources; it's that simple.
Java 必须Closeable
表明您持有的实例可能持有,也可能不持有系统资源;但如果这样做,如果你不这样做.close()
,你就会泄漏资源;就这么简单。
For instance, you may have a method which has an InputStream
as an argument; OK, fine, but what is this InputStream
? Is it a FileInputStream
or a ByteArrayInputStream
, or even something else? You cannot know. The first needs to be closed properly but the second doesn't need to.
例如,你可能有一个方法,它有InputStream
一个参数;好的,好的,但这是什么InputStream
?它是 aFileInputStream
还是 a ByteArrayInputStream
,甚至是其他东西?你不可能知道。第一个需要正确关闭,但第二个不需要。
So what? .close()
them all anyway, you have nothing to lose. Do you really want to take the chance?
所以呢?.close()
无论如何,你没有什么可失去的。你真的想抓住机会吗?
With Java 6, you'll want to use Guava's Closer
, since this is the safest way to have all your resources closed (and the JDK does not provide such a tool):
在 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
}
With Java 7, you have try-with-resources which works with all AutoCloseable
resources (which Closeable
extends):
使用 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
}
The main difference between Closer
and try-with-resources is that with the latter, resources will be closed beforecatch
whereas Closer
will close them in finally
.
Closer
try-with-resources 和 try-with-resources的主要区别在于,对于后者,资源将在之前关闭,catch
而Closer
将在finally
.
But again: don't take a chance. Close them all.
但再说一遍:不要冒险。全部关闭。
回答by bmargulies
It's important to be precise in the use of the term 'memory leak' with respect to Java.
在 Java 中准确使用术语“内存泄漏”很重要。
In Java, a memory leakhappens when your code holds a reference permanently, so that some object is never garbage collected.
在 Java 中,当您的代码永久持有引用时会发生内存泄漏,因此某些对象永远不会被垃圾收集。
Failing to close a stream is not a memory leak in this sense. Streams that have native resources have finalizers; the GC will eventually close them down. Unless you hold a reference to the unclosed stream it isn't a leak.
从这个意义上说,未能关闭流不是内存泄漏。具有本机资源的流具有终结器;GC 最终将关闭它们。除非您持有对未关闭流的引用,否则它不是泄漏。
However, there are other kinds of leaks besides memory leaks. Most operating systems limit the number of open files. If you fail to close your streams, the GC may take a very long time to close them for you; the net result may be that you run out of system file descriptors and your code fails to open one more file. Some people will call this a leak, but it's not accuracy to call it a memory leak.
但是,除了内存泄漏之外,还有其他类型的泄漏。大多数操作系统限制打开文件的数量。如果你没有关闭你的流,GC 可能需要很长时间来为你关闭它们;最终结果可能是您用完了系统文件描述符并且您的代码无法再打开一个文件。有些人会将此称为泄漏,但称其为内存泄漏并不准确。
回答by lorenzo
The answer depends on the stream.
答案取决于流。
A memory leak is simply a situation where you keep around things that you didn't intend to. This is always due to a programming error: someone somewhere forgot to release ("detach" from all strong references) some instances. These add up over time and then you notice the "leak". A cache that grows indefinitely is a good example.
内存泄漏只是一种情况,您保留了您不打算做的事情。这总是由于编程错误:某处有人忘记释放(从所有强引用中“分离”)某些实例。随着时间的推移,这些加起来,然后你会注意到“泄漏”。无限增长的缓存就是一个很好的例子。
A stream, for example, could place some data into a shared container (typically static) like a resource lock, some kind of cache, etc. as soon as it is open/used. And then it cleans up this resource in the close method. So skipping this last part does create a memory leak.
例如,一个流可以将一些数据放入一个共享容器(通常是静态的),如资源锁、某种缓存等,一旦它被打开/使用。然后它在 close 方法中清理此资源。所以跳过这最后一部分确实会造成内存泄漏。
In your example the ByteArrayInputStream.close()method does nothing, so no problem there. BufferedInputStream.close()just delegates the call to the wrapped class so, in this case, again there is no problem.
在您的示例中,ByteArrayInputStream.close()方法什么都不做,所以没问题。BufferedInputStream.close()只是将调用委托给包装类,因此在这种情况下,再次没有问题。
More complex streams dealing with files, network streams can create leaks if not closed but it is not common. I'm assuming that the stream itself is not kept around but left available for collection. In many situations, a "smart" stream may even fix these oversights during its own collection and perform the necessary cleanup by itself (this remains an anomalous situation that the stream should clearly log/notify somewhere).
处理文件的更复杂的流,如果不关闭网络流可能会造成泄漏,但这并不常见。我假设流本身没有保留,而是可供收集。在许多情况下,“智能”流甚至可以在其自己的收集过程中修复这些疏忽并自行执行必要的清理(这仍然是一种异常情况,流应该清楚地记录/通知某处)。