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

发布于 2024-12-08 04:34:39 字数 140 浏览 1 评论 0原文

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

如果查找哪个对象太具体,那么哪个也会非常有帮助。

I need to find out which object in my Java app has a file open. This is for debugging, so tools or utilities are welcome.

If finding which object is too specific, which class would also be very helpful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可可 2024-12-15 04:34:39

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

您的下一步可能是在 FileInputStream 和 FileOutputStream (除非您知道是否该文件正在读取或写入),附加调试器,并观察其中之一打开您的文件。当然,还有其他打开文件的方法。您可能还需要标记诸如 Class.getResourceAsStream()URL.openConnection()

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

That could be tricky. You could start by using a profiler, like VisualVM (free) or YourKit (not free) to inspect java.io.File objects in memory. If you can find one with the path you're interested in, that might point you in the right direction. The problem is that a File object doesn't necessarily have to exist for an app to still have the file open.

Your next step might be to set breakpoints in both FileInputStream and FileOutputStream (unless you know whether the file is being read or written to), attach a debugger, and watch for your file to be opened by one of those. But of course, there are other ways of opening files as well. You might also need to stake out things like Class.getResourceAsStream() and URL.openConnection(), for example.

Your last resort might be to try out an omniscient debugger, like ODB or TOD. I only have limited experience with them, but they claim to "know everything". You'll just have to figure out how to ask the right question.

夜清冷一曲。 2024-12-15 04:34:39

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

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


  1. 找出文件的句柄。为此,您可以使用 Windows Sysinternals 句柄工具(另请参阅< a href="https://serverfault.com/a/1980">此服务器故障问题):
    <前><代码>.\handle64.exe -p java

  2. 在输出中搜索相关文件,例如:
    D7C:文件 C:\Users\Someone\myfile.txt
    

    (注:大多数终端都提供搜索功能,对于cmd.exe来说是Ctrl + F;对于Windows 终端 它是 Ctrl + + F。)
    冒号之前的值很重要(在此示例中为 D7C),请记下它。

  3. 在 IntelliJ 中,使用调试器暂停执行。
  4. 打开内存选项卡
  5. 搜索java.io.FileDescriptor
  6. 右键单击​​结果并选择“显示实例”
  7. 作为条件输入 handle == 0xhandlehandle 是您在步骤 2 中记下的值(在此示例中 handle == 0xD7C)。
    (注意:在 Unix 下,您可能必须比较 fd ==。)
    ➔ 您应该看到一个结果
  8. 右键单击​​结果并选择“显示引用对象...”,
  9. 然后您可以在结果上继续选择“显示引用对象...”,直到找到相关结果(<代码中的引用) >FileCleanable 很可能会被忽略)

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

The following is Windows and IntelliJ specific, though it is likely similar for other operating systems and IDEs.

Additionally it relies on JDK internals, the following has been written for JDK 11.


  1. Find out the handle of the file. For this you can use the Windows Sysinternals Handle tool (see also this Server Fault question):
    .\handle64.exe -p java
    
  2. In the output search for the relevant file, e.g.:
    D7C: File          C:\Users\Someone\myfile.txt
    

    (Note: Most terminals provide a search function, for cmd.exe it is Ctrl + F; for Windows Terminal it is Ctrl + + F.)
    The value before the colon is important (in this example D7C), note it down.

  3. In IntelliJ pause execution with the debugger.
  4. Open the Memory tab
  5. Search for java.io.FileDescriptor
  6. Right-click the result and select "Show Instances"
  7. As condition enter handle == 0xhandle, with handle being the value you noted down in step 2 (in this example handle == 0xD7C).
    (Note: Under Unix you might have to compare fd == instead.)
    ➔ You should see a single result
  8. Right-click the result and select "Show Referring Objects..."
  9. On the results you can then continue selecting "Show Referring Objects..." until you found the relevant result (the reference in FileCleanable can most likely be ignored)

This won't always answer which caller forgot to close the file, but it might give a hint. You can then for example set further breakpoints in the relevant classes to find out who opened the file.

救赎№ 2024-12-15 04:34:39

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

Use AspectJ and intercept calls to various flavors of opening file streams. Use an around aspect. Note this can only tell you which object opens the stream, but obviously the object can pass around references to the stream, so ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文