44

我想知道这是否是必需的,因为当我使用此方法时,正在从类路径中读取文件。“不关闭”它会导致内存泄漏。

如何测试此类内存泄漏?

4

3 回答 3

37

您假设Class.getResourceAsStream()它将始终返回一个指向您的类的 JAR 文件中的文件的流。这是不正确的。您的类路径还可能包含文件夹,在这种情况下Class.getResourceAsStream()将返回一个FileInputStream. 其他一些类加载器也可能返回其他类型的资源,例如远程文件(在 URLClassLoader 的情况下)。

即使在 JAR 文件的情况下,实现也有可能以任何方式在 JAR 文件中维护您正在访问的文件的压缩字节的持久视图。也许它持有一个内存映射ByteBuffer......

为什么要抓住机会?您应该始终关闭流(以及任何其他 Closeable,实际上),无论它们是如何提供给您的。

请注意,从 Java 7 开始,处理关闭任何资源的首选方法肯定是 try-with-resources 构造。它正确地处理了几个在手写代码中很难管理的极端情况,但它对您来说几乎就像您忘记关闭资源一样容易编写。例如,您可以使用如下代码:

    try (InputStream in = Class.getResourceAsStream("someresource.txt")) {
        // Use the stream as you need to...
    }

    // Then forget about it... and yet, it has been closed properly.

至于检测泄漏,最好的策略是在VM关闭时获取内存转储,然后使用一些工具对其进行分析。两个流行的工具是VisualVMEclipse mat

于 2013-10-25T19:41:34.063 回答
8

根据经验,您应该关闭所有流(以及提供关闭功能的任何其他类型)。它可能导致资源泄漏(内存是一种资源)。

虽然当一个对象不再被引用时,自动垃圾回收最终会回收内存,但它可能仍然持有可能不会被释放的本机资源。此外,如果其他一些长期存在的对象(例如类加载器)保留了资源,垃圾收集器将不会声明它。

如果您的程序是短暂的,或者您只打开了少量资源,您可能不会遇到问题,但在长时间运行的应用程序中很难检测到资源泄漏。

于 2013-10-25T19:42:07.427 回答
6

返回的类型是一个输入流,因此,无论具体实现(可能会从一个版本更改为另一个版本),您都有一个应调用 imho 的 close() 方法。

不管该方法是否真的对当前版本有用。

于 2013-10-25T19:40:54.370 回答