【问题标题】:getResourceAsStream returning null after it had workedgetResourceAsStream 工作后返回 null
【发布时间】:2013-11-27 20:14:55
【问题描述】:

我正在从 servlet 容器运行应用程序。此应用程序生成的字母源自一些与 jar 一起打包的文件模板。我通过Class.getResourceAsStrem 获取了这些文件,并且该应用程序运行良好。

然而,在数千次调用之后,该方法突然返回null,并继续返回null,直到应用程序重新启动。我对此没有任何解释,我也看不出为什么会突然发生这种情况。

我首先认为这可能是因为未关闭的流指向相同的资源,但我在打开它后立即将流处理包装在 catch-try-block 中。此外,堆转储不会显示此类流对象,而且我还认为这应该导致 IOException 代替。此外,它在 javadoc 中说

一个 InputStream 对象,如果没有找到同名的资源,则返回 null

但是为什么应用程序突然无法再找到之前成功找到的资源。

有什么想法吗?

【问题讨论】:

  • 这些文件在哪里?
  • 在 jar 的子文件夹中。

标签: java resources


【解决方案1】:

我想我找到了原因。 Class.getResourceAsStream 最终委托给的 ClassLoader.getResourceAsStream(String) 是这样实现的:

public InputStream getResourceAsStream(String name) {
    URL url = getResource(name);
    try {
        return url != null ? url.openStream() : null;
    } catch (IOException e) {
        return null;
    }
}

我猜有一个IOException 正在发生,并且确实存在泄漏的打开文件。但是,这个异常被吞没了,我得到了一个null 指针作为回报。天才 API...

更新:查看堆转储后,我发现应用程序代码正在泄漏文件。该死的,ClassLoader 实现,用NullPointerExceptions 误导我。

【讨论】:

  • After looking at a heap dump.. - 你是怎么得到它的?
  • 我发现OutputStream 的实例位于堆上,这些实例没有关闭但应该已经关闭。 (使用 JVisualVM:docs.oracle.com/javase/6/docs/technotes/tools/share/…)我跟踪了这​​些实例,发现一个流被关闭了两次,而另一个从未关闭过。我猜是典型的复制粘贴。
猜你喜欢
  • 2015-02-19
  • 1970-01-01
  • 2011-07-11
  • 2013-10-02
  • 2013-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多