在 Java 中如何找出哪个对象打开了文件?
我需要找出 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这可能很棘手。您可以首先使用分析器,例如 VisualVM (免费)或 YourKit(非免费)来检查 java.io.File 内存中的对象。如果您能找到一条符合您感兴趣的路径的路径,那可能会为您指明正确的方向。问题在于,应用程序不一定要存在 File 对象才能仍然打开文件。
您的下一步可能是在 FileInputStream 和 FileOutputStream (除非您知道是否该文件正在读取或写入),附加调试器,并观察其中之一打开您的文件。当然,还有其他打开文件的方法。您可能还需要标记诸如 Class.getResourceAsStream() 和 URL.openConnection()。
您最后的手段可能是尝试全知调试器,例如 ODB 或 TOD。我对他们的经验有限,但他们声称“无所不知”。您只需要弄清楚如何提出正确的问题即可。
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.
以下内容特定于 Windows 和 IntelliJ,但对于其他操作系统和 IDE 可能类似。
此外,它依赖于 JDK 内部结构,以下内容是为 JDK 11 编写的。
句柄
。为此,您可以使用 Windows Sysinternals 句柄工具(另请参阅< a href="https://serverfault.com/a/1980">此服务器故障问题):<前><代码>.\handle64.exe -p java
(注:大多数终端都提供搜索功能,对于
cmd.exe
来说是Ctrl + F;对于Windows 终端 它是 Ctrl + ⇧ + F。)冒号之前的值很重要(在此示例中为
D7C
),请记下它。java.io.FileDescriptor
handle == 0xhandle
,handle 是您在步骤 2 中记下的值(在此示例中handle == 0xD7C
)。(注意:在 Unix 下,您可能必须比较
fd ==
。)➔ 您应该看到一个结果
这并不总是回答哪个调用者忘记关闭文件,但它可能会给出提示。然后,您可以在相关类中设置更多断点,以找出谁打开了该文件。
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.
handle
of the file. For this you can use the Windows Sysinternals Handle tool (see also this Server Fault question):(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.java.io.FileDescriptor
handle == 0xhandle
, with handle being the value you noted down in step 2 (in this examplehandle == 0xD7C
).(Note: Under Unix you might have to compare
fd ==
instead.)➔ You should see a single result
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.
使用 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 ...