如何找出哪个线程在java中锁定文件?

我正在尝试删除程序中另一个线程以前使用过的文件。

我无法删除该文件,但我不知道如何确定哪个线程可能正在使用该文件。

那么如何找出哪个线程在java中锁定文件?

我没有一个直接的答案(我不认为也有一个,这是在操作系统级别(本机),而不是在JVM级别控制)我也没有真正看到答案的价值(一旦发现它是哪个线程,你仍然无法以编程方式关闭文件,但我认为你还不知道当文件仍然打开时通常无法删除。 当您没有InputStreamOutputStreamReaderWriter上显式调用Closeable#close()时,可能会发生这种情况。

基本演示:

 public static void main(String[] args) throws Exception { File file = new File("c:/test.txt"); // Precreate this test file first. FileOutputStream output = new FileOutputStream(file); // This opens the file! System.out.println(file.delete()); // false output.close(); // This explicitly closes the file! System.out.println(file.delete()); // true } 

换句话说,确保在整个Java IO内容中代码在使用后正确关闭资源。 正常的习惯用法是在try-with-resources语句中执行此操作,以便您可以确定无论如何都会释放资源,即使在IOException情况下也是如此。 例如

 try (OutputStream output = new FileOutputStream(file)) { // ... } 

任何自动打开的AutoCloseable实现任何 InputStreamOutputStreamReaderWriter等(使用new关键字)。

这在技术上不需要在某些实现上,例如ByteArrayOutputStream ,但为了清楚起见,只需遵循最终的近似成语,以避免误解和重构错误。

如果你还没有使用Java 7或更新版本,那么请使用下面的try-finally成语。

 OutputStream output = null; try { output = new FileOutputStream(file); // ... } finally { if (output != null) try { output.close(); } catch (IOException logOrIgnore) {} } 

希望这有助于确定您特定问题的根本原因。

关于这个问题,我也试着找出这个答案,并提出这个问题并找到答案:

每当JVM线程独占锁定文件时,JVM也会锁定一些Jave对象 ,例如,我发现在我的情况下:

  • sun.nio.fs.NativeBuffer
  • sun.nio.ch.Util $ BufferCache

因此,您只需要找到这个锁定的Java对象并对其进行分析,然后找到哪个线程锁定了您的文件。

我不确定文件是否只是打开(没有锁定),但我确信如果文件被Thread专门锁定(使用java.nio.channels.FileLock,java.nio.channels.FileChannel等)上)

更多信息,请看这个问题