Java watch 服务似乎可以重新创建已删除的文件。到底是怎么回事?

标签 java windows multithreading debugging filesystems

当目录被 WatchService 监控时被删除,其父目录不会立即在其文件的 listFiles 中反射(reflect)删除方法,无法删除。直到整个服务显式 stopped parent 的后果似乎是:

  1. recommended recursive solution用于删除非空目录失败。
  2. deleteOnExit正常终止时未执行
  3. 调用 delete返回 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);
    }
  }  
}

在 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

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

最佳答案

可能相关:

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

The WatchService has an open handle to each watched directory. If a a watch directory is deleted then the WatchService closes the handle so that the directory entry can be removed from the parent directory. A problem arises for utilities and application that expect to be able to delete the parent directory immediately as it can take a few milliseconds for the watch service to get the notificationa and close the handle. If during that time that the tool attempts to delete the parent directory then it will fail. We don't have a solution to this issue at this time.

关于Java watch 服务似乎可以重新创建已删除的文件。到底是怎么回事?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12322143/

相关文章:

windows - 复制最新/最新文件夹窗口的内容

c++ - 列出线程 C++

objective-c - 当在同一个并发队列的 dispatch_sync 中调用 dispatch_apply 时内部会发生什么

c# - 如何在 C# 中使 webdriver 线程安全?

java - Android视频(VideoView)播放时没有音频

java - 在使用 Swing 的 Java 中,我如何知道使用 invokeLater 启动的所有线程何时完成?

windows - 如何将 Windows 命令提示符下发出的命令的 Perl 脚本输出重定向到文本文件

java - Weblogic jms分布式主题

Java7/Path/File/获取唯一ID,如文件的inode

php - PHP 的 "Virtual Directory Support"是我认为的吗?