How Zero‑Copy Supercharges Java Performance: From mmap to Netty

This article explains the concept of zero‑copy, its implementation in Java I/O, NIO, Netty, and popular messaging systems, and shows how techniques like mmap+write and Sendfile eliminate unnecessary data copying to dramatically improve throughput and latency.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
How Zero‑Copy Supercharges Java Performance: From mmap to Netty

I/O Concepts

Buffers are the foundation of all I/O operations; a process issues read or write requests to the operating system, which either drains data from a kernel buffer to user space (write) or fills a user buffer from the kernel (read).

When a read request arrives, the kernel first checks if the required data already resides in kernel space; if so, it copies the data directly to the process buffer. Otherwise, it commands the disk controller to write data into the kernel read buffer via DMA, after which the kernel copies the data to the user buffer. Write operations similarly copy user data to the kernel socket buffer and then to the network card via DMA.

Zero‑copy was introduced to eliminate these costly copies between kernel and user space.

Virtual Memory

Modern operating systems use virtual memory, allowing multiple virtual addresses to map to the same physical memory and enabling a virtual address space larger than physical RAM. By mapping kernel and user virtual addresses to the same physical page, DMA can fill a buffer visible to both spaces, removing the need for extra copies.

Zero‑Copy Techniques

mmap + write

Sendfile

mmap+write Method

Memory‑mapped files map a file or object into a process's address space, establishing a one‑to‑one correspondence between file offsets and virtual addresses. This removes the need for the kernel read buffer to copy data into the user buffer, though a copy from the kernel read buffer to the kernel socket buffer may still occur.

Sendfile Method

The sendfile system call, introduced in kernel 2.1, simplifies data transfer between two channels by eliminating data copies and reducing context switches. Later kernel improvements recorded buffer descriptors directly in the socket buffer, removing even the remaining kernel‑space copy.

Java Zero‑Copy

MappedByteBuffer

Java NIO's FileChannel provides a map() method that creates a virtual memory mapping between a file and a MappedByteBuffer. The buffer behaves like a ByteBuffer, but its data resides on disk and is accessed directly.

public class MappedByteBufferTest {
    public static void main(String[] args) throws Exception {
        File file = new File("D://db.txt");
        long len = file.length();
        byte[] ds = new byte[(int) len];
        MappedByteBuffer mappedByteBuffer = new FileInputStream(file).getChannel()
            .map(FileChannel.MapMode.READ_ONLY, 0, len);
        for (int offset = 0; offset < len; offset++) {
            byte b = mappedByteBuffer.get();
            ds[offset] = b;
        }
        Scanner scan = new Scanner(new ByteArrayInputStream(ds)).useDelimiter(" ");
        while (scan.hasNext()) {
            System.out.print(scan.next() + " ");
        }
    }
}

The map() method signature:

public abstract MappedByteBuffer map(MapMode mode, long position, long size) throws IOException;

Parameters:

MapMode : READ_ONLY, READ_WRITE, PRIVATE.

Position : start offset in bytes.

Size : number of bytes to map.

PRIVATE mode creates a copy‑on‑write mapping where modifications are not reflected in the underlying file.

DirectByteBuffer

DirectByteBuffer

extends MappedByteBuffer and allocates memory outside the JVM heap, avoiding garbage‑collector overhead. It can also be created manually:

ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(100);

Channel‑to‑Channel Transfer

Java's FileChannel.transferTo() moves data directly between channels without an intermediate user‑space buffer.

public class ChannelTransfer {
    public static void main(String[] argv) throws Exception {
        String[] files = new String[1];
        files[0] = "D://db.txt";
        catFiles(Channels.newChannel(System.out), files);
    }
    private static void catFiles(WritableByteChannel target, String[] files) throws Exception {
        for (int i = 0; i < files.length; i++) {
            FileInputStream fis = new FileInputStream(files[i]);
            FileChannel channel = fis.getChannel();
            channel.transferTo(0, channel.size(), target);
            channel.close();
            fis.close();
        }
    }
}

Signature:

public abstract long transferTo(long position, long count, WritableByteChannel target) throws IOException;

This method avoids copying data into a user buffer and leverages kernel buffers for both source and destination.

Netty Zero‑Copy

Netty provides zero‑copy buffers using CompositeChannelBuffer and Slice. Composite buffers combine multiple ChannelBuffer instances without copying their contents, while Slice creates view buffers that share the same underlying memory.

public class CompositeChannelBuffer extends AbstractChannelBuffer {
    private final ByteOrder order;
    private ChannelBuffer[] components;
    private int[] indices;
    private int lastAccessedComponentId;
    private final boolean gathering;
    public byte getByte(int index) {
        int componentId = componentId(index);
        return components[componentId].getByte(index - indices[componentId]);
    }
    ...
}

The buffer holds references to all received buffers; no new memory is allocated, achieving zero‑copy.

Other Zero‑Copy Implementations

RocketMQ writes messages sequentially to a commit log and uses a consume‑queue index; it employs mmap+write for consumer requests. Kafka also uses the Sendfile technique to transfer data from disk to the network without extra copies.

Conclusion

Zero‑copy in Java essentially works by sharing object references so that a single modification is visible to all users, eliminating duplicate copies and significantly improving I/O performance.

Source: ksfzhaohui Link: https://juejin.im/post/5cad6f1ef265da039f0ef5df Copyright notice: Content is shared for learning purposes only; original author retains rights.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javanioNettyZero-Copy
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.