如何找出哪个对象在Java中打开了文件?

时间:2011-10-05 03:05:43

标签: java file file-io io

我需要找到我的Java应用中的哪个对象打开一个文件。这是用于调试的,因此欢迎使用工具或实用程序。

如果找到哪个对象过于具体,哪个也会非常有帮助。

3 个答案:

答案 0 :(得分:4)

这可能很棘手。您可以首先使用分析器,例如VisualVM(免费)或YourKit(非免费)来检查内存中的java.io.File个对象。如果你能找到一个你感兴趣的路径,那可能会指向你正确的方向。问题是,对于仍然打开文件的应用程序,不一定存在File对象。

您的下一步可能是在FileInputStreamFileOutputStream中设置断点(除非您知道是否正在读取或写入文件),附加调试器,并注意您的文件是其中一个开了。但当然,还有其他打开文件的方法。例如,您可能还需要放弃Class.getResourceAsStream()URL.openConnection()之类的内容。

您的最后一招可能是尝试使用无所不知的调试器,例如ODBTOD。我对他们只有有限的经验,但他们声称“知道一切”。你只需要弄清楚如何提出正确的问题。

答案 1 :(得分:0)

使用AspectJ并拦截对各种开放文件流的调用。使用周围的方面。请注意,这只能告诉您哪个对象打开了流,但显然该对象可以传递对流的引用,所以......

答案 2 :(得分:0)

以下是特定于 Windows 和 IntelliJ 的,但对于其他操作系统和 IDE 可能类似。

此外,它依赖于 JDK 内部,以下是为 JDK 11 编写的。


  1. 找出文件的 handle。为此,您可以使用 Windows Sysinternals Handle tool(另请参阅 this Server Fault question):
    .\handle64.exe -p java
    
  2. 在输出中搜索相关文件,例如:
    D7C: File          C:\Users\Someone\myfile.txt
    
    (注意:大多数终端都提供搜索功能,对于cmd.exeCtrl + F;对于Windows TerminalCtrl + + F.)
    冒号前的值很重要(在本例中为 D7C),记下它。
  3. 在 IntelliJ 中,使用调试器暂停执行。
  4. 打开Memory tab
  5. 搜索java.io.FileDescriptor
  6. 右键单击结果并选择“显示实例”
  7. 作为条件输入 handle == 0xhandlehandle 是您在第 2 步中记下的值(在本例中为 handle == 0xD7C)。
    (注意:在 Unix 下,您可能需要比较 fd ==。)
    ➔ 您应该看到一个结果
  8. 右键单击结果并选择“显示引用对象...”
  9. 在结果中,您可以继续选择“显示引用对象...”,直到找到相关结果(FileCleanable 中的引用很可能会被忽略)

这不会总是回答哪个调用者忘记关闭文件,但它可能会给出提示。例如,您可以在相关类中设置更多断点以找出谁打开了文件。