应该关闭Class.getResourceAsStream吗?

时间:2013-10-25 19:36:19

标签: java

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

我如何测试此类内存泄漏?

3 个答案:

答案 0 :(得分:22)

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

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

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

请注意,从Java 8开始,处理关闭任何资源的首选方法绝对是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关闭时获取内存转储,然后使用某个工具进行分析。两个常用工具是jhatEclipse mat

答案 1 :(得分:6)

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

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

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

答案 2 :(得分:4)

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

无论该方法是否实际上对当前版本做了一些有用的事情。