12.4 Real-World Applications and Integration

Apply memory segment techniques in production scenarios for databases, networking, image processing, and high-performance computing.

Application 1: High-Performance Binary Database

import java.lang.foreign.*;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.util.*;

public class BinaryDatabase implements AutoCloseable {
    private final Path dataFile;
    private final FileChannel channel;
    private final Arena arena;
    private MemorySegment data;

    // Database format:
    // Header (32 bytes):
    //   - Magic (4): 0x42444230 ("BDB0")
    //   - Version (4)
    //   - Record count (8)
    //   - Record size (4)
    //   - Flags (4)
    //   - Reserved (8)
    // Records: Fixed size records

    private static final int HEADER_SIZE = 32;
    private static final int MAGIC = 0x42444230;

    private int recordSize;
    private long recordCount;

    public BinaryDatabase(Path dataFile, int recordSize) throws Exception {
        this.dataFile = dataFile;
        this.recordSize = recordSize;
        this.arena = Arena.ofShared();

        if (Files.exists(dataFile)) {
            openExisting();
        } else {
            createNew();
        }
    }

    private void createNew() throws Exception {
        // Create new database file
        this.channel = FileChannel.open(
            dataFile,
            StandardOpenOption.CREATE,
            StandardOpenOption.READ,
            StandardOpenOption.WRITE
        );

        // Initialize with header only
        long initialSize = HEADER_SIZE;
        this.data = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            initialSize,
            arena
        );

        // Write header
        data.set(ValueLayout.JAVA_INT, 0, MAGIC);
        data.set(ValueLayout.JAVA_INT, 4, 1);  // Version
        data.set(ValueLayout.JAVA_LONG, 8, 0L);  // Record count
        data.set(ValueLayout.JAVA_INT, 16, recordSize);
        data.set(ValueLayout.JAVA_INT, 20, 0);  // Flags

        this.recordCount = 0;
    }

    private void openExisting() throws Exception {
        this.channel = FileChannel.open(
            dataFile,
            StandardOpenOption.READ,
            StandardOpenOption.WRITE
        );

        long fileSize = channel.size();
        this.data = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            fileSize,
            arena
        );

        // Read header
        int magic = data.get(ValueLayout.JAVA_INT, 0);
        if (magic != MAGIC) {
            throw new IllegalStateException("Invalid database file");
        }

        this.recordCount = data.get(ValueLayout.JAVA_LONG, 8);
        this.recordSize = data.get(ValueLayout.JAVA_INT, 16);
    }

    /**
     * Insert record at end
     */
    public long insert(byte[] recordData) throws Exception {
        if (recordData.length != recordSize) {
            throw new IllegalArgumentException(
                "Record must be " + recordSize + " bytes"
            );
        }

        // Grow file if needed
        long requiredSize = HEADER_SIZE + ((recordCount + 1) * recordSize);
        if (requiredSize > data.byteSize()) {
            growFile(requiredSize);
        }

        // Write record
        long recordOffset = HEADER_SIZE + (recordCount * recordSize);
        MemorySegment.copy(
            recordData, 0,
            data, ValueLayout.JAVA_BYTE, recordOffset,
            recordSize
        );

        // Update count
        recordCount++;
        data.set(ValueLayout.JAVA_LONG, 8, recordCount);

        return recordCount - 1;  // Return record ID
    }

    /**
     * Read record by ID
     */
    public Optional<byte[]> read(long recordId) {
        if (recordId < 0 || recordId >= recordCount) {
            return Optional.empty();
        }

        long recordOffset = HEADER_SIZE + (recordId * recordSize);
        byte[] record = new byte[recordSize];

        MemorySegment.copy(
            data, ValueLayout.JAVA_BYTE, recordOffset,
            record, 0,
            recordSize
        );

        return Optional.of(record);
    }

    /**
     * Update existing record
     */
    public boolean update(long recordId, byte[] recordData) {
        if (recordId < 0 || recordId >= recordCount) {
            return false;
        }

        if (recordData.length != recordSize) {
            throw new IllegalArgumentException("Invalid record size");
        }

        long recordOffset = HEADER_SIZE + (recordId * recordSize);
        MemorySegment.copy(
            recordData, 0,
            data, ValueLayout.JAVA_BYTE, recordOffset,
            recordSize
        );

        return true;
    }

    /**
     * Scan all records with predicate
     */
    public List<Long> scan(java.util.function.Predicate<byte[]> predicate) {
        List<Long> matches = new ArrayList<>();
        byte[] record = new byte[recordSize];

        for (long i = 0; i < recordCount; i++) {
            long offset = HEADER_SIZE + (i * recordSize);
            MemorySegment.copy(
                data, ValueLayout.JAVA_BYTE, offset,
                record, 0,
                recordSize
            );

            if (predicate.test(record)) {
                matches.add(i);
            }
        }

        return matches;
    }

    private void growFile(long newSize) throws Exception {
        // Close current mapping
        data = null;

        // Remap with larger size
        data = channel.map(
            FileChannel.MapMode.READ_WRITE,
            0,
            newSize,
            arena
        );
    }

    public long getRecordCount() {
        return recordCount;
    }

    @Override
    public void close() throws Exception {
        if (channel != null) {
            channel.close();
        }
        arena.close();
    }

    // Example usage
    public static void main(String[] args) throws Exception {
        Path dbPath = Paths.get("data.db");

        // Create database with 64-byte records
        try (BinaryDatabase db = new BinaryDatabase(dbPath, 64)) {
            // Insert records
            for (int i = 0; i < 1000; i++) {
                byte[] record = new byte[64];
                // Fill record with data
                record[0] = (byte) i;
                record[1] = (byte) (i >> 8);

                long id = db.insert(record);
                if (i % 100 == 0) {
                    System.out.println("Inserted record " + id);
                }
            }

            System.out.println("Total records: " + db.getRecordCount());

            // Read record
            Optional<byte[]> record = db.read(500);
            record.ifPresent(r -> 
                System.out.println("Record 500 first byte: " + (r[0] & 0xFF))
            );

            // Scan for matching records
            List<Long> matches = db.scan(r -> (r[0] & 0xFF) > 200);
            System.out.println("Found " + matches.size() + " matching records");
        }
    }
}

Application 2: Network Packet Processor

import java.lang.foreign.*;
import java.net.*;
import java.nio.channels.*;
import java.util.concurrent.*;

public class PacketProcessor {
    private final Arena arena;
    private final ExecutorService executor;
    private final MemoryPool bufferPool;

    // Ethernet frame layout
    private static final MemoryLayout ETHERNET_HEADER = MemoryLayout.structLayout(
        MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_BYTE).withName("dst_mac"),
        MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_BYTE).withName("src_mac"),
        ValueLayout.JAVA_SHORT.withName("ethertype")
    );

    // IPv4 header (simplified)
    private static final MemoryLayout IP_HEADER = MemoryLayout.structLayout(
        ValueLayout.JAVA_BYTE.withName("version_ihl"),
        ValueLayout.JAVA_BYTE.withName("tos"),
        ValueLayout.JAVA_SHORT.withName("total_length"),
        ValueLayout.JAVA_SHORT.withName("identification"),
        ValueLayout.JAVA_SHORT.withName("flags_fragment"),
        ValueLayout.JAVA_BYTE.withName("ttl"),
        ValueLayout.JAVA_BYTE.withName("protocol"),
        ValueLayout.JAVA_SHORT.withName("checksum"),
        ValueLayout.JAVA_INT.withName("src_ip"),
        ValueLayout.JAVA_INT.withName("dst_ip")
    );

    public PacketProcessor(int threads) {
        this.arena = Arena.ofShared();
        this.executor = Executors.newFixedThreadPool(threads);
        this.bufferPool = new MemoryPool(2048, 100, 1000);
    }

    public void processPacket(DatagramChannel channel) throws Exception {
        MemorySegment buffer = bufferPool.acquire();

        try {
            // Receive packet into native memory
            int bytesRead = channel.read(buffer.asByteBuffer());

            if (bytesRead > 0) {
                MemorySegment packet = buffer.asSlice(0, bytesRead);

                // Submit for async processing
                executor.submit(() -> {
                    try {
                        analyzePacket(packet);
                    } finally {
                        bufferPool.release(buffer);
                    }
                });
            } else {
                bufferPool.release(buffer);
            }

        } catch (Exception e) {
            bufferPool.release(buffer);
            throw e;
        }
    }

    private void analyzePacket(MemorySegment packet) {
        // Parse Ethernet header
        if (packet.byteSize() < 14) {
            return;  // Too short
        }

        short ethertype = packet.get(ValueLayout.JAVA_SHORT, 12);

        if (ethertype == (short) 0x0800) {  // IPv4
            parseIPv4(packet.asSlice(14));
        }
    }

    private void parseIPv4(MemorySegment ipPacket) {
        if (ipPacket.byteSize() < 20) {
            return;  // Too short for IP header
        }

        byte versionIhl = ipPacket.get(ValueLayout.JAVA_BYTE, 0);
        int version = (versionIhl >> 4) & 0x0F;
        int headerLength = (versionIhl & 0x0F) * 4;

        if (version != 4) {
            return;  // Not IPv4
        }

        // Extract fields
        short totalLength = ipPacket.get(ValueLayout.JAVA_SHORT, 2);
        byte ttl = ipPacket.get(ValueLayout.JAVA_BYTE, 8);
        byte protocol = ipPacket.get(ValueLayout.JAVA_BYTE, 9);
        int srcIp = ipPacket.get(ValueLayout.JAVA_INT, 12);
        int dstIp = ipPacket.get(ValueLayout.JAVA_INT, 16);

        System.out.printf(
            "IPv4: src=%s dst=%s proto=%d ttl=%d len=%d\n",
            formatIP(srcIp),
            formatIP(dstIp),
            protocol & 0xFF,
            ttl & 0xFF,
            totalLength & 0xFFFF
        );
    }

    private String formatIP(int ip) {
        return String.format(
            "%d.%d.%d.%d",
            (ip >> 24) & 0xFF,
            (ip >> 16) & 0xFF,
            (ip >> 8) & 0xFF,
            ip & 0xFF
        );
    }

    public void shutdown() {
        executor.shutdown();
        bufferPool.close();
        arena.close();
    }
}

Application 3: Image Processing

import java.lang.foreign.*;
import java.nio.file.*;

public class ImageProcessor {
    // BMP file header (simplified)
    private static final int BMP_HEADER_SIZE = 54;

    public record Image(int width, int height, MemorySegment pixels) {}

    /**
     * Load BMP image from file (24-bit RGB)
     */
    public static Image loadBMP(Path file, Arena arena) throws Exception {
        byte[] fileData = Files.readAllBytes(file);
        MemorySegment fileSegment = arena.allocateArray(
            ValueLayout.JAVA_BYTE,
            fileData
        );

        // Parse header
        int width = fileSegment.get(ValueLayout.JAVA_INT, 18);
        int height = fileSegment.get(ValueLayout.JAVA_INT, 22);

        // Extract pixel data
        int pixelDataSize = width * height * 3;  // 24-bit RGB
        MemorySegment pixels = arena.allocate(pixelDataSize);

        MemorySegment.copy(
            fileSegment, ValueLayout.JAVA_BYTE, BMP_HEADER_SIZE,
            pixels, ValueLayout.JAVA_BYTE, 0,
            pixelDataSize
        );

        return new Image(width, height, pixels);
    }

    /**
     * Convert to grayscale
     */
    public static Image toGrayscale(Image image, Arena arena) {
        int width = image.width;
        int height = image.height;

        // Allocate grayscale image (1 byte per pixel)
        MemorySegment grayPixels = arena.allocate(width * height);

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                long rgbOffset = (y * width + x) * 3;

                // Read RGB
                int b = image.pixels.get(ValueLayout.JAVA_BYTE, rgbOffset) & 0xFF;
                int g = image.pixels.get(ValueLayout.JAVA_BYTE, rgbOffset + 1) & 0xFF;
                int r = image.pixels.get(ValueLayout.JAVA_BYTE, rgbOffset + 2) & 0xFF;

                // Convert to grayscale
                int gray = (int) (0.299 * r + 0.587 * g + 0.114 * b);

                long grayOffset = y * width + x;
                grayPixels.set(ValueLayout.JAVA_BYTE, grayOffset, (byte) gray);
            }
        }

        return new Image(width, height, grayPixels);
    }

    /**
     * Apply box blur filter
     */
    public static Image boxBlur(Image image, int radius, Arena arena) {
        int width = image.width;
        int height = image.height;
        MemorySegment result = arena.allocate(width * height);

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int sum = 0;
                int count = 0;

                // Sum neighbors
                for (int dy = -radius; dy <= radius; dy++) {
                    for (int dx = -radius; dx <= radius; dx++) {
                        int nx = x + dx;
                        int ny = y + dy;

                        if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                            long offset = ny * width + nx;
                            int value = image.pixels.get(
                                ValueLayout.JAVA_BYTE,
                                offset
                            ) & 0xFF;
                            sum += value;
                            count++;
                        }
                    }
                }

                // Average
                int avg = sum / count;
                long offset = y * width + x;
                result.set(ValueLayout.JAVA_BYTE, offset, (byte) avg);
            }
        }

        return new Image(width, height, result);
    }

    /**
     * Histogram calculation
     */
    public static int[] histogram(Image image) {
        int[] hist = new int[256];
        long pixelCount = image.pixels.byteSize();

        for (long i = 0; i < pixelCount; i++) {
            int value = image.pixels.get(ValueLayout.JAVA_BYTE, i) & 0xFF;
            hist[value]++;
        }

        return hist;
    }
}

Application 4: Scientific Computing - Matrix Operations

import java.lang.foreign.*;

public class Matrix {
    private final MemorySegment data;
    private final int rows;
    private final int cols;

    public Matrix(Arena arena, int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        this.data = arena.allocate(
            rows * cols * ValueLayout.JAVA_DOUBLE.byteSize()
        );

        // Initialize to zero
        data.fill((byte) 0);
    }

    public void set(int row, int col, double value) {
        long offset = (row * cols + col) * 8L;
        data.set(ValueLayout.JAVA_DOUBLE, offset, value);
    }

    public double get(int row, int col) {
        long offset = (row * cols + col) * 8L;
        return data.get(ValueLayout.JAVA_DOUBLE, offset);
    }

    /**
     * Matrix multiplication: C = A * B
     */
    public static Matrix multiply(Matrix a, Matrix b, Arena arena) {
        if (a.cols != b.rows) {
            throw new IllegalArgumentException("Incompatible dimensions");
        }

        Matrix result = new Matrix(arena, a.rows, b.cols);

        // Standard matrix multiplication
        for (int i = 0; i < a.rows; i++) {
            for (int j = 0; j < b.cols; j++) {
                double sum = 0.0;

                for (int k = 0; k < a.cols; k++) {
                    sum += a.get(i, k) * b.get(k, j);
                }

                result.set(i, j, sum);
            }
        }

        return result;
    }

    /**
     * Transpose matrix
     */
    public Matrix transpose(Arena arena) {
        Matrix result = new Matrix(arena, cols, rows);

        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                result.set(j, i, get(i, j));
            }
        }

        return result;
    }

    /**
     * In-place scalar multiplication
     */
    public void scale(double scalar) {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                set(i, j, get(i, j) * scalar);
            }
        }
    }

    public void print() {
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                System.out.printf("%.2f ", get(i, j));
            }
            System.out.println();
        }
    }

    // Example usage
    public static void main(String[] args) {
        try (Arena arena = Arena.ofConfined()) {
            // Create matrices
            Matrix a = new Matrix(arena, 3, 3);
            Matrix b = new Matrix(arena, 3, 3);

            // Fill with data
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    a.set(i, j, i + j);
                    b.set(i, j, i * j);
                }
            }

            System.out.println("Matrix A:");
            a.print();

            System.out.println("\nMatrix B:");
            b.print();

            // Multiply
            Matrix c = Matrix.multiply(a, b, arena);
            System.out.println("\nA * B:");
            c.print();

            // Transpose
            Matrix at = a.transpose(arena);
            System.out.println("\nA^T:");
            at.print();
        }
    }
}

Integration Patterns

Pattern 1: JNI Replacement:

// Old JNI approach
public native int processData(byte[] data);

// New FFM approach
public int processData(byte[] data) throws Throwable {
    try (Arena arena = Arena.ofConfined()) {
        Linker linker = Linker.nativeLinker();
        SymbolLookup lib = SymbolLookup.loaderLookup();

        MethodHandle processData = linker.downcallHandle(
            lib.find("process_data").orElseThrow(),
            FunctionDescriptor.of(
                ValueLayout.JAVA_INT,
                ValueLayout.ADDRESS,
                ValueLayout.JAVA_INT
            )
        );

        MemorySegment nativeData = arena.allocateArray(
            ValueLayout.JAVA_BYTE,
            data
        );

        return (int) processData.invoke(nativeData, data.length);
    }
}

Pattern 2: Async I/O Integration:

import java.nio.channels.*;
import java.util.concurrent.*;

public class AsyncMemoryIO {
    public CompletableFuture<Integer> readAsync(
            AsynchronousFileChannel channel,
            long position,
            int size
    ) {
        CompletableFuture<Integer> future = new CompletableFuture<>();

        try (Arena arena = Arena.ofConfined()) {
            MemorySegment buffer = arena.allocate(size);
            java.nio.ByteBuffer byteBuffer = buffer.asByteBuffer();

            channel.read(byteBuffer, position, null, 
                new CompletionHandler<Integer, Void>() {
                    @Override
                    public void completed(Integer result, Void attachment) {
                        future.complete(result);
                    }

                    @Override
                    public void failed(Throwable exc, Void attachment) {
                        future.completeExceptionally(exc);
                    }
                }
            );
        }

        return future;
    }
}

Best Practices Summary

1. Choose Right Arena Scope:

  • Request scope: Arena.ofConfined() for single-threaded operations
  • Session scope: Arena.ofShared() for multi-threaded access
  • Application scope: Arena.global() sparingly

2. Optimize for Access Patterns:

  • Sequential access: Use streaming operations
  • Random access: Consider memory-mapped files
  • Concurrent access: Use appropriate synchronization

3. Memory Efficiency:

  • Reuse allocations with pools
  • Use zero-copy when possible
  • Align data for cache efficiency

4. Error Handling:

  • Validate sizes and offsets
  • Handle native errors gracefully
  • Clean up resources in finally blocks

5. Performance Testing:

  • Benchmark against Java heap alternatives
  • Profile memory access patterns
  • Measure actual throughput improvements

These real-world applications demonstrate the power and flexibility of MemorySegment for high-performance Java applications.