Home/Learn/Java A–Z/NIO.2 — Non-Blocking I/O

NIO.2 — Non-Blocking I/O

Advanced
I/O and Networking

NIO.2 provides asynchronous file I/O, file system watching, and high-performance channel-based I/O for demanding applications.

Overview

NIO.2 (introduced in Java 7 via java.nio.file and extended in java.nio.channels) adds asynchronous I/O, a file-system watch service, symbolic link support, and the Path/Files API. AsynchronousFileChannel and AsynchronousSocketChannel allow I/O without blocking threads — operations complete via callbacks or Future. WatchService monitors directories for changes in real time.

Path and FileSystem API

Path is the NIO.2 replacement for java.io.File. It is immutable and works with any filesystem (default, ZIP filesystem, in-memory). Paths.get() and Path.of() create instances.

Files complements Path with utility methods. Path supports resolve(), relativize(), normalize(), and toAbsolutePath().

PathAPI.java
import java.nio.file.*;

Path base    = Path.of("/home/user/projects");
Path subPath = base.resolve("myapp/src/Main.java");
// /home/user/projects/myapp/src/Main.java

Path relative = base.relativize(subPath);
// myapp/src/Main.java

Path norm = Path.of("/home/user/../user/./projects").normalize();
// /home/user/projects

// Path components
System.out.println(subPath.getFileName());  // Main.java
System.out.println(subPath.getParent());    // .../src
System.out.println(subPath.getRoot());      // /
System.out.println(subPath.getNameCount()); // 5

// Check file attributes
System.out.println(Files.isReadable(subPath));
System.out.println(Files.size(subPath));
System.out.println(Files.getLastModifiedTime(subPath));

WatchService — File System Events

WatchService monitors a directory for create, modify, and delete events. The watch loop polls for WatchKey objects; each key holds a list of WatchEvent objects with the changed path.

This is the Java equivalent of inotify on Linux. Useful for hot-reload, config watching, and build tools.

WatchService.java
import java.nio.file.*;

WatchService watcher = FileSystems.getDefault().newWatchService();

Path dir = Path.of("config");
dir.register(watcher,
    StandardWatchEventKinds.ENTRY_CREATE,
    StandardWatchEventKinds.ENTRY_MODIFY,
    StandardWatchEventKinds.ENTRY_DELETE);

System.out.println("Watching: " + dir);

while (true) {
    WatchKey key = watcher.take(); // blocks until event

    for (WatchEvent<?> event : key.pollEvents()) {
        WatchEvent.Kind<?> kind = event.kind();
        Path changed = (Path) event.context();
        System.out.println(kind + ": " + changed);
    }

    boolean valid = key.reset();
    if (!valid) break; // directory deleted — stop
}

AsynchronousFileChannel

AsynchronousFileChannel reads and writes without blocking the calling thread. Operations return CompletableFuture-compatible Future objects or use CompletionHandler callbacks.

This is essential for high-throughput servers where blocking I/O would exhaust thread pools.

AsyncFileChannel.java
import java.nio.channels.*;
import java.nio.ByteBuffer;
import java.nio.file.*;

Path path = Path.of("large-file.bin");

try (AsynchronousFileChannel afc = AsynchronousFileChannel.open(
        path, StandardOpenOption.READ)) {

    ByteBuffer buf = ByteBuffer.allocate(1024);
    long position = 0;

    // Callback style
    afc.read(buf, position, buf, new CompletionHandler<>() {
        @Override
        public void completed(Integer result, ByteBuffer attachment) {
            attachment.flip();
            byte[] data = new byte[attachment.limit()];
            attachment.get(data);
            System.out.println("Read " + result + " bytes");
        }

        @Override
        public void failed(Throwable exc, ByteBuffer attachment) {
            System.err.println("Read failed: " + exc.getMessage());
        }
    });
}

Key Points to Remember

  • Path is immutable and replaces java.io.File for NIO.2 operations.
  • resolve() appends a path; relativize() computes relative path; normalize() cleans . and ..
  • WatchService monitors directories for ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE events.
  • AsynchronousFileChannel reads/writes without blocking, using callbacks or Future.
  • Always call key.reset() in the WatchService loop to continue receiving events.

Practice NIO.2 — Non-Blocking I/O in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

What is the difference between java.io.File and java.nio.file.Path?

EasyOracle
2

How does WatchService work and what are its use cases?

MediumGoogle
3

What is AsynchronousFileChannel and how does it differ from FileChannel?

HardAmazon
4

Why is it important to call key.reset() in a WatchService loop?

MediumMicrosoft
5

How would you implement a config hot-reload mechanism using WatchService?

HardNetflix

Ask Aria about NIO.2 — Non-Blocking I/O

Your personal AI tutor — ask anything about this concept