WatchService for File System Monitoring
Fast recall
Quick revision
Core answer
WatchService is NIO's low-level directory-change notification API. Register each directory for event kinds, wait for WatchKeys, process and reset each key, and treat events as change hints that may be delayed, coalesced, or overflowed.Interview-ready guide
Interview answer
WatchService is Java NIO's low-level API for receiving notifications about changes to registered objects, most commonly directories. A file system creates the service, directories register event kinds, and each registration returns a WatchKey. The service queues a key when events are available for that directory.
A watcher normally calls take() to block or poll() to check with optional timeout. It obtains the key's events, examines each kind and relative context Path, then calls reset() so the key can receive more notifications. If reset returns false, the key is invalid—often because the directory is inaccessible or deleted—and the registration should no longer be trusted.
For example, a development tool can register a configuration directory for create, modify, and delete events. When settings.json changes, it re-reads and validates the complete file rather than assuming one modify event describes every write. OVERFLOW means events may have been lost or discarded, so the application needs a rescan or other recovery strategy.
Implementations are file-system and platform dependent. Event timing and ordering vary, repeated changes may be coalesced, and a file can change again or disappear before it is processed. Registering a parent does not recursively register existing or future child directories; a recursive watcher must discover and register each directory and handle newly created directories.
WatchService is useful for cache invalidation, reload hints, developer tools, and responsive local monitoring. It is not a durable audit log or a cross-system message bus. Correct designs combine it with current-state validation, overflow recovery, lifecycle shutdown, and periodic reconciliation when missing a change would matter.
WatchService for File System Monitoring
Direct Answer
WatchService is NIO's low-level directory-change notification API. Register each directory for event kinds, wait for WatchKeys, process and reset each key, and treat events as change hints that may be delayed, coalesced, or overflowed.
Deep Dive & Architecture
A WatchKey groups events for one registration. Once signalled, it remains signalled until events are processed and the key is reset. Resetting is therefore part of the protocol rather than cleanup decoration. If a loop forgets it, that registration stops producing the expected future wakeups.
The event context for directory registration is commonly a relative Path such as settings.json. Resolve it against the watched directory before accessing the entry. By that time the entry may have been replaced, renamed, or removed, so consumers should perform the complete read they need and handle ordinary file-system failures.
Overflow changes the trust model. It says the implementation may have discarded events, not which state is wrong. The safe recovery is to compare the watched tree with a known inventory or rebuild derived state. Systems that require every historical change need a durable journal supplied by the storage platform or by the application itself.
Shutdown also deserves design. Closing the WatchService invalidates registered keys and wakes threads blocked in take with ClosedWatchServiceException. An application should own the watching thread, close the service during shutdown, and avoid leaking a forever-blocked non-daemon thread.
Code Example
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.TimeUnit;
class WatchDirectory {
public static void main(String[] args) throws Exception {
Path directory = Files.createTempDirectory("watch-");
Path created = directory.resolve("note.txt");
try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
directory.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
Files.writeString(created, "ready", StandardCharsets.UTF_8);
WatchKey key = watcher.poll(1, TimeUnit.SECONDS);
boolean sawFile = false;
if (key != null) {
sawFile = key.pollEvents().stream()
.anyMatch(event -> event.context().equals(Path.of("note.txt")));
if (!key.reset()) throw new AssertionError("key became invalid");
}
if (!Files.exists(created)) throw new AssertionError("reconciliation failed");
System.out.println(sawFile ? "event observed" : "state found by rescan");
} finally {
Files.deleteIfExists(created);
Files.deleteIfExists(directory);
}
}
}
Check your understanding
Answer these without looking back at the article.
- Why must a WatchKey be reset after its events are processed?
- What should an application do after an OVERFLOW event?
- Does registering a directory watch all descendants recursively?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.