or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cpp-core.mdflexbuffers.mdgo.mdindex.mdjava.mdjavascript.mdpython.mdrust.mdschema-compiler.mdverification.md
tile.json

java.mddocs/

Java

Java implementation of FlatBuffers providing type-safe access to FlatBuffer data with integration into Java's memory model and garbage collection system. The Java binding maintains zero-copy deserialization benefits while providing idiomatic Java APIs.

Capabilities

Installation and Dependencies

Add FlatBuffers to your Java project using Maven or Gradle.

<!-- Maven dependency -->
<dependency>
    <groupId>com.google.flatbuffers</groupId>
    <artifactId>flatbuffers-java</artifactId>
    <version>25.2.10</version>
</dependency>
// Gradle dependency
implementation 'com.google.flatbuffers:flatbuffers-java:25.2.10'
// Core imports
import com.google.flatbuffers.FlatBufferBuilder;
import com.google.flatbuffers.Table;
import com.google.flatbuffers.Struct;

// Utility imports
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

FlatBufferBuilder Class

Main builder class for constructing FlatBuffer data in Java applications.

public class FlatBufferBuilder {
    /**
     * Create a FlatBufferBuilder with default initial size
     */
    public FlatBufferBuilder();
    
    /**
     * Create a FlatBufferBuilder with specified initial size
     * @param initialSize Initial buffer size in bytes
     */
    public FlatBufferBuilder(int initialSize);
    
    /**
     * Create a FlatBufferBuilder with custom ByteBuffer
     * @param bb Custom ByteBuffer to use
     * @param file_identifier Optional 4-character file identifier
     */
    public FlatBufferBuilder(ByteBuffer bb, String file_identifier);
    
    /**
     * Reset the builder for reuse
     */
    public void clear();
    
    /**
     * Get current buffer size
     * @return Size in bytes
     */
    public int offset();
    
    /**
     * Create string and return its offset
     * @param s String to store
     * @return Offset to string
     */
    public int createString(CharSequence s);
    public int createString(ByteBuffer s);
    
    /**
     * Create vector of bytes
     * @param arr Byte array to store
     * @return Offset to vector
     */
    public int createByteVector(byte[] arr);
    
    /**
     * Create vector of shorts
     * @param arr Short array to store  
     * @return Offset to vector
     */
    public int createShortVector(short[] arr);
    
    /**
     * Create vector of ints
     * @param arr Integer array to store
     * @return Offset to vector
     */
    public int createIntVector(int[] arr);
    
    /**
     * Create vector of longs
     * @param arr Long array to store
     * @return Offset to vector
     */
    public int createLongVector(long[] arr);
    
    /**
     * Create vector of floats
     * @param arr Float array to store
     * @return Offset to vector
     */
    public int createFloatVector(float[] arr);
    
    /**
     * Create vector of doubles
     * @param arr Double array to store
     * @return Offset to vector
     */
    public int createDoubleVector(double[] arr);
    
    /**
     * Start building a vector manually
     * @param elemSize Size of each element in bytes
     * @param numElems Number of elements
     * @param alignment Required alignment
     */
    public void startVector(int elemSize, int numElems, int alignment);
    
    /**
     * End vector construction
     * @return Offset to completed vector
     */
    public int endVector();
    
    /**
     * Start building a table
     * @param numFields Number of fields in table
     */
    public void startTable(int numFields);
    
    /**
     * Add byte field to current table
     * @param o Field offset in vtable
     * @param x Value to store
     * @param d Default value
     */
    public void addByte(int o, byte x, byte d);
    
    /**
     * Add short field to current table
     * @param o Field offset in vtable
     * @param x Value to store  
     * @param d Default value
     */
    public void addShort(int o, short x, short d);
    
    /**
     * Add int field to current table
     * @param o Field offset in vtable
     * @param x Value to store
     * @param d Default value  
     */
    public void addInt(int o, int x, int d);
    
    /**
     * Add long field to current table
     * @param o Field offset in vtable
     * @param x Value to store
     * @param d Default value
     */
    public void addLong(int o, long x, long d);
    
    /**
     * Add float field to current table
     * @param o Field offset in vtable
     * @param x Value to store
     * @param d Default value
     */
    public void addFloat(int o, float x, float d);
    
    /**
     * Add double field to current table
     * @param o Field offset in vtable  
     * @param x Value to store
     * @param d Default value
     */
    public void addDouble(int o, double x, double d);
    
    /**
     * Add offset field to current table
     * @param o Field offset in vtable
     * @param x Offset value
     * @param d Default offset
     */
    public void addOffset(int o, int x, int d);
    
    /**
     * Add struct field to current table
     * @param o Field offset in vtable
     * @param x Struct offset
     * @param d Default offset
     */
    public void addStruct(int o, int x, int d);
    
    /**
     * End table construction
     * @return Offset to completed table
     */
    public int endTable();
    
    /**
     * Finish buffer with root table
     * @param rootTable Offset to root table
     */
    public void finish(int rootTable);
    
    /**
     * Finish buffer with root table and file identifier
     * @param rootTable Offset to root table
     * @param file_identifier 4-character identifier
     */
    public void finish(int rootTable, String file_identifier);
    
    /**
     * Finish buffer with size prefix
     * @param rootTable Offset to root table
     */
    public void finishSizePrefixed(int rootTable);
    
    /**
     * Get the underlying ByteBuffer
     * @return ByteBuffer containing data
     */
    public ByteBuffer dataBuffer();
    
    /**
     * Get buffer data as byte array
     * @return Byte array copy of buffer
     */
    public byte[] sizedByteArray();
    
    /**
     * Get buffer data as byte array with specific range
     * @param start Start position
     * @param length Length to copy
     * @return Byte array copy of specified range
     */
    public byte[] sizedByteArray(int start, int length);
}

Usage Example:

import com.google.flatbuffers.FlatBufferBuilder;

// Create builder
FlatBufferBuilder builder = new FlatBufferBuilder(1024);

// Create string
int nameOffset = builder.createString("Player");

// Create vector
int[] scores = {100, 200, 300, 400, 500};
int scoresOffset = builder.createIntVector(scores);

// Create table
builder.startTable(3);
builder.addOffset(0, nameOffset, 0);    // name field
builder.addInt(1, 42, 0);               // level field
builder.addOffset(2, scoresOffset, 0);  // scores field
int player = builder.endTable();

// Finish buffer
builder.finish(player);

// Get binary data
byte[] buffer = builder.sizedByteArray();
ByteBuffer bb = builder.dataBuffer();

Table Class

Base class for accessing FlatBuffer table data with type-safe field access.

public class Table {
    /** ByteBuffer containing the table data */
    protected ByteBuffer bb;
    
    /** Position of this table in the buffer */
    protected int bb_pos;
    
    /**
     * Get field offset from vtable
     * @param vtableOffset Offset in vtable
     * @return Field offset or 0 if not present
     */
    protected int __offset(int vtableOffset);
    
    /**
     * Get indirect offset (for tables, vectors, strings)
     * @param offset Field offset
     * @return Indirect offset
     */
    protected int __indirect(int offset);
    
    /**
     * Get string at offset
     * @param offset String offset
     * @return String value or null
     */
    protected String __string(int offset);
    
    /**
     * Get string at offset with encoding
     * @param offset String offset
     * @param encoding Character encoding
     * @return String value or null
     */
    protected String __string(int offset, String encoding);
    
    /**
     * Get vector length at offset
     * @param offset Vector offset
     * @return Vector length
     */
    protected int __vector_len(int offset);
    
    /**
     * Get vector starting position
     * @param offset Vector offset
     * @return Position of first element
     */
    protected int __vector(int offset);
    
    /**
     * Get vector element at index
     * @param offset Vector offset
     * @param j Element index
     * @param elem_size Size of each element
     * @return Element position
     */
    protected int __element(int offset, int j, int elem_size);
    
    /**
     * Get union table at offset
     * @param offset Union offset
     * @return Table instance or null
     */
    protected Table __union(int offset);
    
    /**
     * Get ByteBuffer as byte array
     * @return Byte array copy of buffer
     */
    protected byte[] __vector_as_bytebuffer(int offset);
    
    /**
     * Get ByteBuffer starting at vector
     * @param offset Vector offset
     * @param elem_size Size of each element
     * @return ByteBuffer view of vector data
     */
    protected ByteBuffer __vector_as_bytebuffer(int offset, int elem_size);
}

Generated Code Structure

When using flatc --java, the compiler generates Java classes following these patterns.

// Example generated Java (from monster.fbs):

import com.google.flatbuffers.*;
import java.nio.ByteBuffer;

public final class Vec3 extends Struct {
    public Vec3 __assign(int _i, ByteBuffer _bb) {
        __init(_i, _bb);
        return this;
    }
    
    public float x() { 
        return bb.getFloat(bb_pos + 0); 
    }
    
    public float y() { 
        return bb.getFloat(bb_pos + 4); 
    }
    
    public float z() { 
        return bb.getFloat(bb_pos + 8); 
    }
    
    public static int pack(FlatBufferBuilder builder, float x, float y, float z) {
        builder.prep(4, 12);
        builder.putFloat(z);
        builder.putFloat(y);
        builder.putFloat(x);
        return builder.offset();
    }
}

public final class Monster extends Table {
    public static void ValidateVersion() { 
        Constants.FLATBUFFERS_25_2_10(); 
    }
    
    public static Monster getRootAs(ByteBuffer _bb) {
        return getRootAs(_bb, new Monster());
    }
    
    public static Monster getRootAs(ByteBuffer _bb, Monster obj) {
        _bb.order(ByteOrder.LITTLE_ENDIAN);
        return obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb);
    }
    
    public void __init(int _i, ByteBuffer _bb) {
        __reset(_i, _bb);
    }
    
    public Monster __assign(int _i, ByteBuffer _bb) {
        __init(_i, _bb);
        return this;
    }
    
    public Vec3 pos() {
        return pos(new Vec3());
    }
    
    public Vec3 pos(Vec3 obj) {
        int o = __offset(4);
        return o != 0 ? obj.__assign(bb_pos + o, bb) : null;
    }
    
    public short mana() {
        int o = __offset(6);
        return o != 0 ? bb.getShort(o + bb_pos) : 150;
    }
    
    public short hp() {
        int o = __offset(8);
        return o != 0 ? bb.getShort(o + bb_pos) : 100;
    }
    
    public String name() {
        int o = __offset(10);
        return o != 0 ? __string(o + bb_pos) : null;
    }
    
    public int inventory(int j) {
        int o = __offset(14);
        return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0;
    }
    
    public int inventoryLength() {
        int o = __offset(14);
        return o != 0 ? __vector_len(o) : 0;
    }
    
    public ByteBuffer inventoryAsByteBuffer() {
        return __vector_as_bytebuffer(14, 1);
    }
    
    public ByteBuffer inventoryInByteBuffer(ByteBuffer _bb) {
        return __vector_in_bytebuffer(_bb, 14, 1);
    }
    
    public static int createMonster(FlatBufferBuilder builder,
                                   int pos,
                                   short mana,
                                   short hp,
                                   int name,
                                   int inventory) {
        builder.startTable(6);
        Monster.addInventory(builder, inventory);
        Monster.addName(builder, name);
        Monster.addPos(builder, pos);
        Monster.addHp(builder, hp);
        Monster.addMana(builder, mana);
        return Monster.endMonster(builder);
    }
    
    public static void startMonster(FlatBufferBuilder builder) {
        builder.startTable(6);
    }
    
    public static void addPos(FlatBufferBuilder builder, int pos) {
        builder.addStruct(0, pos, 0);
    }
    
    public static void addMana(FlatBufferBuilder builder, short mana) {
        builder.addShort(1, mana, 150);
    }
    
    public static void addHp(FlatBufferBuilder builder, short hp) {
        builder.addShort(2, hp, 100);
    }
    
    public static void addName(FlatBufferBuilder builder, int name) {
        builder.addOffset(3, name, 0);
    }
    
    public static void addInventory(FlatBufferBuilder builder, int inventory) {
        builder.addOffset(5, inventory, 0);
    }
    
    public static int createInventoryVector(FlatBufferBuilder builder, byte[] data) {
        return builder.createByteVector(data);
    }
    
    public static void startInventoryVector(FlatBufferBuilder builder, int numElems) {
        builder.startVector(1, numElems, 1);
    }
    
    public static int endMonster(FlatBufferBuilder builder) {
        int o = builder.endTable();
        return o;
    }
}

ByteBuffer Integration

FlatBuffers Java integrates seamlessly with Java NIO ByteBuffer for efficient memory management.

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import com.google.flatbuffers.FlatBufferBuilder;

// Working with ByteBuffers
public class ByteBufferUtils {
    /**
     * Create FlatBufferBuilder from existing ByteBuffer
     * @param bb Existing ByteBuffer
     * @return FlatBufferBuilder using the buffer
     */
    public static FlatBufferBuilder fromByteBuffer(ByteBuffer bb) {
        bb.order(ByteOrder.LITTLE_ENDIAN);
        return new FlatBufferBuilder(bb);
    }
    
    /**
     * Read FlatBuffer from ByteBuffer
     * @param bb ByteBuffer containing FlatBuffer data
     * @return Root table position
     */
    public static int getRootOffset(ByteBuffer bb) {
        bb.order(ByteOrder.LITTLE_ENDIAN);
        return bb.getInt(bb.position()) + bb.position();
    }
    
    /**
     * Create read-only view of buffer data
     * @param builder Completed FlatBufferBuilder
     * @return Read-only ByteBuffer
     */
    public static ByteBuffer asReadOnlyBuffer(FlatBufferBuilder builder) {
        return builder.dataBuffer().asReadOnlyBuffer();
    }
}

File I/O and Serialization

Working with files and streams in Java.

import java.io.*;
import java.nio.file.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FlatBufferIO {
    /**
     * Save FlatBuffer to file
     * @param builder Completed FlatBufferBuilder
     * @param filename Output file path
     * @throws IOException If write fails
     */
    public static void saveToFile(FlatBufferBuilder builder, String filename) throws IOException {
        byte[] data = builder.sizedByteArray();
        Files.write(Paths.get(filename), data);
    }
    
    /**
     * Load FlatBuffer from file
     * @param filename Input file path
     * @return ByteBuffer containing data
     * @throws IOException If read fails
     */
    public static ByteBuffer loadFromFile(String filename) throws IOException {
        byte[] data = Files.readAllBytes(Paths.get(filename));
        ByteBuffer bb = ByteBuffer.wrap(data);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        return bb;
    }
    
    /**
     * Save FlatBuffer using FileChannel for large files
     * @param builder Completed FlatBufferBuilder
     * @param filename Output file path
     * @throws IOException If write fails
     */
    public static void saveWithChannel(FlatBufferBuilder builder, String filename) throws IOException {
        try (FileChannel channel = FileChannel.open(Paths.get(filename), 
                                                   StandardOpenOption.CREATE,
                                                   StandardOpenOption.WRITE,
                                                   StandardOpenOption.TRUNCATE_EXISTING)) {
            ByteBuffer buffer = builder.dataBuffer();
            channel.write(buffer);
        }
    }
    
    /**
     * Write FlatBuffer to OutputStream
     * @param builder Completed FlatBufferBuilder
     * @param out Output stream
     * @throws IOException If write fails
     */
    public static void writeToStream(FlatBufferBuilder builder, OutputStream out) throws IOException {
        byte[] data = builder.sizedByteArray();
        out.write(data);
    }
    
    /**
     * Read FlatBuffer from InputStream
     * @param in Input stream
     * @return ByteBuffer containing data
     * @throws IOException If read fails
     */
    public static ByteBuffer readFromStream(InputStream in) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        byte[] chunk = new byte[8192];
        int bytesRead;
        while ((bytesRead = in.read(chunk)) != -1) {
            buffer.write(chunk, 0, bytesRead);
        }
        
        ByteBuffer bb = ByteBuffer.wrap(buffer.toByteArray());
        bb.order(ByteOrder.LITTLE_ENDIAN);
        return bb;
    }
}

Complete Usage Example:

import com.google.flatbuffers.*;
import java.nio.ByteBuffer;
import java.io.IOException;

// Import generated classes
import MyGame.Sample.Monster;
import MyGame.Sample.Vec3;

public class FlatBufferExample {
    public static void main(String[] args) throws IOException {
        // Create monster
        FlatBufferBuilder builder = new FlatBufferBuilder(1024);
        
        // Create components
        int name = builder.createString("Dragon");
        int pos = Vec3.pack(builder, 1.0f, 2.0f, 3.0f);
        byte[] inventoryData = {1, 2, 3, 4, 5};
        int inventory = builder.createByteVector(inventoryData);
        
        // Build monster
        int monster = Monster.createMonster(builder, pos, (short)200, (short)150, name, inventory);
        
        // Finish buffer
        builder.finish(monster);
        
        // Get binary data
        byte[] buffer = builder.sizedByteArray();
        
        // Read the data back
        ByteBuffer bb = ByteBuffer.wrap(buffer);
        Monster readMonster = Monster.getRootAs(bb);
        
        System.out.println("Name: " + readMonster.name());
        System.out.println("HP: " + readMonster.hp());
        System.out.println("Mana: " + readMonster.mana());
        
        Vec3 position = readMonster.pos();
        if (position != null) {
            System.out.println("Position: " + position.x() + ", " + position.y() + ", " + position.z());
        }
        
        System.out.println("Inventory size: " + readMonster.inventoryLength());
        for (int i = 0; i < readMonster.inventoryLength(); i++) {
            System.out.println("Item " + i + ": " + readMonster.inventory(i));
        }
        
        // Save to file
        FlatBufferIO.saveToFile(builder, "monster.bin");
        
        // Load from file
        ByteBuffer loadedBuffer = FlatBufferIO.loadFromFile("monster.bin");
        Monster loadedMonster = Monster.getRootAs(loadedBuffer);
        System.out.println("Loaded name: " + loadedMonster.name());
    }
}