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.