title: Watch service acquiring file handle
body: <p>I am using java watch service in my application to get notified of any file changes.</p>
  
  <p>But the problem is watch service holds the file handle of the parent directory.
  For e.g. if my hierarchy is</p>
  
  <pre><code>F
  -F1
   -F2
  </code></pre>
  
  <p>When i register watch service on F, F1 and F2. Then if i try to rename or delete the  parent folder F, there comes a message of file is opened by another program which is the watch service.</p>
  
  <p>I have found this issue mentioned here <a href="http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=76a42b61021a94ffffffffa049f7587fd4149?bug_id=6972833" rel="nofollow">http://bugs.java.com/bugdatabase/view_bug.do;jsessionid=76a42b61021a94ffffffffa049f7587fd4149?bug_id=6972833</a></p>
  
  <p>Also have tried the File_Tree modifier to circumvent this issue but it did not help. Probably i have not used the File_Tree modifier properly.</p>
  
  <p>Below is the sample code which i am testing on. Please check if the usage of FILE_TREE modifier is proper in my code.</p>
  
  <pre><code>/**
   * Example to watch a directory (or tree) for changes to files.
   * This code is direct copy from https://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java
   */
  
  public class FileWatcher {
  
      private final WatchService watcher;
      private final Map&lt;WatchKey,Path&gt; keys;
      private final boolean recursive;
      private boolean trace = false;
  
      @SuppressWarnings("unchecked")
      static &lt;T&gt; WatchEvent&lt;T&gt; cast(WatchEvent&lt;?&gt; event) {
          return (WatchEvent&lt;T&gt;)event;
      }
  
      /**
       * Register the given directory with the WatchService
       */
      private void register(Path dir) throws IOException {
          WatchKey key = dir.register(watcher, new WatchEvent.Kind[] { ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY, OVERFLOW },com.sun.nio.file.ExtendedWatchEventModifier.FILE_TREE);
          if (trace) {
              Path prev = keys.get(key);
              if (prev == null) {
                  System.out.format("register: %s\n", dir);
              } else {
                  if (!dir.equals(prev)) {
                      System.out.format("update: %s -&gt; %s\n", prev, dir);
                  }
              }
          }
          keys.put(key, dir);
      }
  
      /**
       * Register the given directory, and all its sub-directories, with the
       * WatchService.
       */
      private void registerAll(final Path start) throws IOException {
          // register directory and sub-directories
          Files.walkFileTree(start, new SimpleFileVisitor&lt;Path&gt;() {
              @Override
              public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                      throws IOException
                      {
                  register(dir);
                  return FileVisitResult.CONTINUE;
                      }
          });
      }
  
      /**
       * Creates a WatchService and registers the given directory
       */
      FileWatcher(Path dir, boolean recursive) throws IOException {
          this.watcher = FileSystems.getDefault().newWatchService();
          this.keys = new HashMap&lt;WatchKey,Path&gt;();
          this.recursive = recursive;
  
          if (recursive) {
              System.out.format("Scanning %s ...\n", dir);
              registerAll(dir);
              System.out.println("Done.");
          } else {
              register(dir);
          }
  
          // enable trace after initial registration
          this.trace = true;
      }
  
      /**
       * Process all events for keys queued to the watcher
       */
      void processEvents() {
          for (;;) {
  
              // wait for key to be signalled
              WatchKey key;
              try {
                  key = watcher.take();
              } catch (InterruptedException x) {
                  return;
              }
  
              Path dir = keys.get(key);
              if (dir == null) {
                  System.err.println("WatchKey not recognized!!");
                  continue;
              }
  
              for (WatchEvent&lt;?&gt; event: key.pollEvents()) {
                  WatchEvent.Kind kind = event.kind();
  
                  // TBD - provide example of how OVERFLOW event is handled
                  if (kind == OVERFLOW) {
                      continue;
                  }
  
                  // Context for directory entry event is the file name of entry
                  WatchEvent&lt;Path&gt; ev = cast(event);
                  Path name = ev.context();
                  Path child = dir.resolve(name);
  
                  // print out event
                  System.out.format("%s: %s\n", event.kind().name(), child);
  
                  // if directory is created, and watching recursively, then
                  // register it and its sub-directories
                  if (recursive &amp;&amp; kind == ENTRY_CREATE) {
                      try {
                          if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                              registerAll(child);
                          }
                      } catch (IOException x) {
                          // ignore to keep sample readbale
                      }
                  }
              }
  
              // reset key and remove from set if directory no longer accessible
              boolean valid = key.reset();
              if (!valid) {
                  keys.remove(key);
  
                  // all directories are inaccessible
                  if (keys.isEmpty()) {
                      break;
                  }
              }
          }
      }
  
      static void usage() {
          System.err.println("usage: java WatchDir [-r] dir");
          System.exit(-1);
      }
  
      public static void main(String[] args) throws IOException {
          // parse arguments
          if (args.length == 0 || args.length &gt; 2) {
              usage();
          }
          boolean recursive = false;
          int dirArg = 0;
          if (args[0].equals("-r")) {
              if (args.length &lt; 2) {
                  usage();
              }
              recursive = false;
              dirArg++;
          }
  
          // register directory and process its events
          Path dir = Paths.get(args[dirArg]);
          new FileWatcher(dir, recursive).processEvents();
      }
  }
  </code></pre>