简体   繁体   English

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

[英]How can I find out which object has a file open in Java?

I need to find out which object in my Java app has a file open.我需要找出我的 Java 应用程序中的哪个对象打开了文件。 This is for debugging, so tools or utilities are welcome.这是用于调试,因此欢迎使用工具或实用程序。

If finding which object is too specific, which class would also be very helpful.如果找到哪个对象太具体,哪个也会很有帮助。

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.您可以首先使用分析器,如VisualVM (免费)或YourKit (非免费)来检查内存中的java.io.File对象。 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.您的下一步可能是在FileInputStreamFileOutputStream 中设置断点(除非您知道文件是被读取还是写入),附加调试器,并观察您的文件是否被其中之一打开。 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.例如,您可能还需要放样Class.getResourceAsStream()URL.openConnection() 之类的东西。

Your last resort might be to try out an omniscient debugger, like ODB or TOD .你最后的手段可能是尝试一个无所不知的调试器,比如ODBTOD 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.你只需要弄清楚如何提出正确的问题。

Use AspectJ and intercept calls to various flavors of opening file streams.使用 AspectJ 并拦截对各种打开文件流的调用。 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 ...请注意,这只能告诉您哪个对象打开了流,但显然该对象可以传递对流的引用,所以......

The following is Windows and IntelliJ specific, though it is likely similar for other operating systems and IDEs.以下是 Windows 和 IntelliJ 特定的,尽管它可能与其他操作系统和 IDE 类似。

Additionally it relies on JDK internals, the following has been written for JDK 11.此外,它依赖于 JDK 内部结构,以下是为 JDK 11 编写的。


  1. Find out the handle of the file.找出文件的handle For this you can use the Windows Sysinternals Handle tool (see also this Server Fault question ):为此,您可以使用 Windows Sysinternals Handle 工具(另请参阅此服务器故障问题):
     .\\handle64.exe -p java
  2. In the output search for the relevant file, eg:在输出中搜索相关文件,例如:
     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 .) (注意:大多数终端提供搜索功能,对于cmd.exeCtrl + F ;对于Windows 终端Ctrl + + F 。)
    The value before the colon is important (in this example D7C ), note it down.冒号前的值很重要(在本例中为D7C ),记下它。
  3. In IntelliJ pause execution with the debugger.在 IntelliJ 中,使用调试器暂停执行。
  4. Open the Memory tab打开内存选项卡
  5. Search for java.io.FileDescriptor搜索java.io.FileDescriptor
  6. Right-click the result and select "Show Instances"右键单击结果并选择“显示实例”
  7. As condition enter handle == 0x handle , with handle being the value you noted down in step 2 (in this example handle == 0xD7C ).作为条件输入handle == 0x handlehandle是您在第 2 步中记下的值(在此示例中handle == 0xD7C )。
    (Note: Under Unix you might have to compare fd == instead.) (注意:在 Unix 下,您可能必须比较fd == 。)
    ➔ 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)在结果上,您可以继续选择“显示引用对象...”,直到找到相关结果( FileCleanable的引用很可能会被忽略)

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.例如,您可以在相关类中设置更多断点以找出谁打开了文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM