通过进程识别打开的 FileOutputStreams

Identify open FileOutputStreams by the process

我们的 Java 应用程序存在内存泄漏,因为 FileOutputStream 打开的数量 - 关闭的差异随时间增加。在我们的例子中,堆非常稳定,但是由于 FileOutputStreams 是打开的,我们面临着 JVM 本机内存中的内存泄漏。

能否请您提出一种方法,我们可以通过该方法识别代码库中可能导致此泄漏的代码段。

在 Linux 系统上 lsof 将帮助您识别哪些文件句柄是打开的,如果您识别出这些名称可能会帮助您追踪代码中未正确关闭资源的位置.

但是,如果您只是使用一个好的 IDE,则有一种更简单的方法,因为当资源面临未关闭的风险时,它们会发出警告。

例如,Eclipse 会用 fis1 可能无法正确关闭的警告标记此行:

FileInputStream fis1 = new FileInputStream(file);
    

... 如果更改为:

,则警告消失
try(FileInputStream fis2 = new FileInputStream(file)) {
}

在JProfiler中,您可以这样找到未关闭的FileOutputStreams的分配点:

  1. 记录分配并拍摄堆快照
  2. Select FileOutputStream 的所有实例并创建一个新对象集
  3. Select“传出参考”视图
  4. Select FileOutputStream 实例的“closed”字段并调用“Apply filter->By restricting the selected value”,然后在值中 select “false”对话框。
  5. 转到堆遍历器的“分配”视图并检查分配调用堆栈树或分配热点视图。

YourKit 探查器自动查找所有 non-closed FileInputStreams:

  • 捕获并打开内存快照。

  • Select“检查”选项卡。

  • 在检查树中找到“Other memory oddities”节点。它包含“未关闭的资源等待完成”。

  • 运行检查.

Profiler 还能够找到 non-closed 文件、目录流、在终结器中关闭的流以及许多其他问题。更多详细信息,请访问 https://www.yourkit.com/docs/java/help/event_inspections.jsp