Java监视服务似乎重新创建已删除的文件.到底是怎么回事?

Mil*_*son 6 java windows filesystems debugging multithreading

WatchService监视的目录被删除时,其父目录不会立即反映其文件的listFiles方法中的删除,并且无法删除.在明确停止整个服务之前,父母的后果似乎是:

  1. 删除非空目录的推荐递归解决方案失败.
  2. deleteOnExit未在正常终止时执行
  3. 调用删除返回false并且对文件系统没有影响.

为了演示,这个测试代码:

import java.io.*;
import java.nio.file.*;

class DirectoryTester { 
  static WatchService watcher; 
  static {
    try{watcher = FileSystems.getDefault().newWatchService();} 
    catch (IOException e) {e.printStackTrace();}
  }

  public static void main(String[] args) throws IOException {
    String SEPARATE = System.getProperty("file.separator");
    String testDirName = System.getProperty("user.dir") + SEPARATE + "testDir";
    String subDirName = testDirName + SEPARATE + "subDir";
    String fileName = subDirName + SEPARATE +"aFile";
    create(fileName);
    Paths.get(subDirName).register(watcher, StandardWatchEventKinds.ENTRY_DELETE);
    delete(new File(testDirName));
  }

  static void create(String nameOfFile) throws IOException {
    new File(nameOfFile).getParentFile().mkdirs();
    Files.createFile(Paths.get(nameOfFile));
    System.out.println("Created " + nameOfFile);
  }     

  static void delete(File toDelete) throws IOException {
    if (toDelete.isDirectory())
      for (File c : toDelete.listFiles()) 
        delete(c);
    int numContainedFiles = toDelete.listFiles() != null ? toDelete.listFiles().length : 0;
    if (!toDelete.delete()) {
      System.out.println("Failed to delete " + toDelete + " containing " + numContainedFiles);
    }
    else {
      System.out.println("Deleted " + toDelete + " containing " + numContainedFiles);
    }
  }  
}
Run Code Online (Sandbox Code Playgroud)

在Windows上提供以下输出,对应于testDir未在文件系统上删除.

Created C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir\aFile
Deleted C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir\aFile containing 0
Deleted C:\Dropbox\CodeSpace\JavaTestbed\src\testDir\subDir containing 0
Failed to delete C:\Dropbox\CodeSpace\JavaTestbed\src\testDir containing 1
Run Code Online (Sandbox Code Playgroud)

如果我在subDir删除后放置一个断点,我可以看到它实际上已经在文件系统上删除了.从断点恢复会导致上次删除被取消,这表明这可能是监视服务线程所做更改的可见性的问题.有谁知道这里发生了什么,如果它是一个错误?我实际上要做的是删除受监视的目录而不停止对其他目录的监视,因为似乎没有API提供的取消注册路径方法,其他标准Java方法是什么?

irr*_*ble 7

可能相关:

http://bugs.sun.com/view_bug.do?bug_id=6972833

WatchService具有每个监视目录的打开句柄.如果删除了监视目录,则WatchService会关闭句柄,以便可以从父目录中删除目录条目.期望能够立即删除父目录的实用程序和应用程序出现问题,因为监视服务可能需要几毫秒来获取通知并关闭句柄.如果在此期间该工具尝试删除父目录,则它将失败.目前我们还没有解决此问题的方法.