It seems when you watch a directory using Java's WatchService and then try to rename its parent directory, the renaming will fail with an AccessDeniedException. The directory seems to be sort of locked by the WatchService.
Can be reproduced with:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.nio.file.*;
public class WatcherTest {
@Test
public void moveWatchedDir(@TempDir Path tempDir) throws Exception {
Files.createDirectories(tempDir.resolve("dir1/dir2"));
var watchService = FileSystems.getDefault().newWatchService();
tempDir.resolve("dir1/dir2").register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
Files.move(tempDir.resolve("dir1"), tempDir.resolve("dir1_b"));
}
}
Fails with:
java.nio.file.AccessDeniedException: C:\Users\Markus\AppData\Local\Temp\junit14649009910061913524\dir1 -> C:\Users\Markus\AppData\Local\Temp\junit14649009910061913524\dir1_b
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:89)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
at java.base/sun.nio.fs.WindowsFileCopy.move(WindowsFileCopy.java:395)
at java.base/sun.nio.fs.WindowsFileSystemProvider.move(WindowsFileSystemProvider.java:292)
at java.base/java.nio.file.Files.move(Files.java:1426)
at WatcherTest.moveWatchedDir(WatcherTest.java:13)
Tested with OpenJDK 11 & 14 on Windows 10. Trying to rename dir1 in Windows Explorer also fails. Works as expected on Linux.
Also note, that when the watcher is not registered on dir1/dir2 but only on dir1 it works.
Is this a bug in OpenJDK
? Looking at some older issues (https://bugs.openjdk.java.net/browse/JDK-8153925) it seems that locking of directories should not happen.
@jurez answer is correct, on Windows the WatchService will lock directories. This is a known OpenJDK issue and apparently can't be fixed.
But there is a great workaround. On Windows it is possible to watch an entire directory structure without having to manually register watchers for each sub dir as on Linux.
This should solve this issue in many situations. With this workaround I only need to watch/lock the top level dir, which should not cause issues for users.