【问题标题】:How to find unclosed I/O resources in Java?如何在 Java 中找到未关闭的 I/O 资源?
【发布时间】:2011-11-12 16:15:14
【问题描述】:

Java 中的许多 I/O 资源(如 InputStream 和 OutputStream)在完成后需要关闭,如 here 所述。

如何在我的项目中搜索未关闭此类资源的地方,例如这种错误:

private void readFile(File file) throws IOException {
    InputStream in = new FileInputStream(file);
    int nextByte = in.read();
    while (nextByte != -1) {
        // Do something with the byte here
        // ...
        // Read the next byte
        nextByte = in.read();
    }
    // Oops! Not closing the InputStream
}

我尝试了一些静态分析工具,例如 PMD 和 FindBugs,但它们并没有将上述代码标记为错误。

【问题讨论】:

标签: java resources io static-analysis


【解决方案1】:

这可能是设置的问题 - 我通过我的 IDE 插件运行了 FindBugs,它报告了 OS_OPEN_STREAM。

【讨论】:

  • 您能详细说明一下在 FindBugs 中需要进行哪些设置吗? IMO,这应该默认启用,考虑到应用程序在用完 ulimit 时崩溃的副作用。
【解决方案2】:

如果修改规则的 FindBugs 对您不起作用,另一种较慢的方法是堆分析。 VisualVM 允许您使用 OQL 查询在任何给定时间在堆转储中打开的特定类型的所有对象。然后,您可以检查打开到在程序中此时不应访问的文件的流。

运行它很简单:

%>jvisualvm

选择正在运行的进程。选择选项保存堆转储(或类似的东西),打开堆转储并在浏览器中查看文件流的类实例,或查询它们。

【讨论】:

  • 我认为如果关联的流只在本机内存(vm_allocate)上留下内存分配并且您想要追踪这些流,则此方法不起作用。它们已经被垃圾回收了(所以它们不会出现在堆上),但它们没有清理本机内存。
【解决方案3】:

在 Java 7 中,他们添加了在当前范围内使用可关闭资源的功能(所谓的 try-with-resources),例如:

public void someMethod() {
    try(InputStream is = new FileInputStream(file)) {
        //do something here
    } // the stream is closed here
}

在旧版本中,常用技术是使用 try-catch-finally 链。

【讨论】:

  • 好的,换句话说,我的问题是在 Java 6 或更早版本中,我怎样才能找到不使用“try then finally close”技术的实例?
  • Google 表示 FindBugs 能够找到此类错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多