Recommended Free Tools
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Java SBE (Simple Binary Encoding) is a schema-driven binary codec generator for systems that need compact messages, predictable parsing and low allocation. You define a message in XML, run the SBE compiler, and use generated Java encoders and decoders over Agrona buffers. SBE handles presentation of bytes; it does not provide transport, retries, ordering, persistence or security.
That trade-off is deliberate. SBE is less flexible than JSON or Protocol Buffers, but its fixed layout and flyweight-style access suit market data, trading, telemetry, RPC and other latency-sensitive workloads.
The Java SBE mental model
messages.xml
│
▼
SBE schema parser and validator
│
▼
Generated Java encoders and decoders
│
▼
Agrona DirectBuffer / MutableDirectBuffer
│
▼
Aeron, TCP, UDP, files, shared memory or another transport
The XML schema is the wire contract. The SBE tool validates it and generates source code. Encoders write to a mutable Agrona buffer; decoders read from a DirectBuffer. The transport is an independent design decision. Aeron is a common companion, not a requirement.
The reference project also generates codecs for languages including C, C++, C#, Go and Rust. Java SBE therefore means the Java implementation and generated-code workflow, not a Java-only serialization format.
#1 Best Overall
Why use SBE?
- Predictable layout: fixed-width fields have known offsets and widths.
- Low allocation potential: generated flyweights can read and write directly in a buffer instead of building an object graph.
- Compact binary messages: usually smaller than text representations.
- Schema governance: IDs, versions and explicit types make changes reviewable.
- Cross-language interoperability: the same schema can generate codecs for several languages.
These are design goals, not universal benchmark results. Throughput and latency depend on message shape, buffer implementation, JIT warm-up, CPU, garbage collection, bounds checks, transport and the quality of the competing codec. The project describes SBE as intended for high-throughput and predictable-latency applications, but measure your own workload.
Install and generate at build time
The SBE compiler is primarily a build-time dependency. Applications normally package generated classes and the compatible Agrona dependency rather than invoking the compiler for every message. Pin a tested SBE version. The official changelog visibly lists 1.37.1 as a January 13, 2026 release; verify Maven Central before selecting a version, and do not assume an old tutorial’s Agrona version is current.
The documented executable-JAR form is:
java
--add-opens java.base/jdk.internal.misc=ALL-UNNAMED
-jar sbe-all-${SBE_TOOL_VERSION}.jar
messages.xml
Useful system properties include:
-Dsbe.output.dir=build/generated/sbe
-Dsbe.target.language=Java
-Dsbe.validation.xsd=src/main/resources/sbe/sbe.xsd
-Dsbe.validation.stop.on.error=true
The tool defaults to Java generation. Add the generated directory to your source set and make compilation depend on generation. A Gradle-style task can look like this (dependency declarations vary by project):
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11tasks.register("generateSbe", JavaExec) {
classpath = configurations.sbeTool
mainClass = "uk.co.real_logic.sbe.SbeTool"
systemProperties = [
"sbe.output.dir": "$buildDir/generated/sbe",
"sbe.target.language": "Java",
"sbe.validation.xsd": "$projectDir/src/main/resources/sbe/sbe.xsd",
"sbe.validation.stop.on.error": "true"
]
args "$projectDir/src/main/resources/messages.xml"
}
For Maven, the project’s documented approach uses exec-maven-plugin and build-helper-maven-plugin; there is no dedicated Maven plugin in that setup. Keep schema validation in CI so malformed or incompatible schemas fail the build.
Rank #2
A minimal schema
<?xml version="1.0" encoding="UTF-8"?>
<sbe:messageSchema
xmlns:sbe="http://fixprotocol.io/2016/sbe"
package="com.example.sbe"
id="100"
version="1"
semanticVersion="1.0.0"
description="Example messages"
byteOrder="littleEndian">
<types>
<composite name="messageHeader">
<type name="blockLength" primitiveType="uint16"/>
<type name="templateId" primitiveType="uint16"/>
<type name="schemaId" primitiveType="uint16"/>
<type name="version" primitiveType="uint16"/>
</composite>
<enum name="Side" encodingType="char">
<validValue name="BUY">66</validValue>
<validValue name="SELL">83</validValue>
</enum>
<type name="Sequence" primitiveType="int64"/>
</types>
<message name="Order" id="1">
<field name="sequence" id="1" type="Sequence"/>
<field name="side" id="2" type="Side"/>
</message>
</sbe:messageSchema>
The namespace, metadata, header, IDs and byte order are part of the protocol. IDs must be unique in their relevant scope. SBE’s structural order is significant: ordinary fields come first, repeating groups follow, and variable-length data comes last. Composite types are constrained wire layouts, not arbitrary nested Java objects.
Encoding and decoding a message
Generated names vary with the schema and tool version, so treat this as representative:
final MutableDirectBuffer buffer =
new UnsafeBuffer(new byte[1024]);
final MessageHeaderEncoder header = new MessageHeaderEncoder();
final OrderEncoder order = new OrderEncoder();
header.wrap(buffer, 0)
.blockLength(OrderEncoder.BLOCK_LENGTH)
.templateId(OrderEncoder.TEMPLATE_ID)
.schemaId(OrderEncoder.SCHEMA_ID)
.version(OrderEncoder.SCHEMA_VERSION);
order.wrap(buffer, MessageHeaderEncoder.ENCODED_LENGTH)
.sequence(42)
.side(Side.BUY);
final MessageHeaderDecoder headerIn = new MessageHeaderDecoder();
final OrderDecoder orderIn = new OrderDecoder();
headerIn.wrap(buffer, 0);
if (headerIn.schemaId() != OrderDecoder.SCHEMA_ID ||
headerIn.templateId() != OrderDecoder.TEMPLATE_ID) {
throw new IllegalArgumentException("Unsupported message");
}
orderIn.wrap(buffer,
MessageHeaderDecoder.ENCODED_LENGTH,
headerIn.blockLength(),
headerIn.version());
long sequence = orderIn.sequence();
Side side = orderIn.side();
The four header values identify the schema family and message template, describe the fixed block and carry the acting version. A decoder must start at the correct offset and use the header values; otherwise valid bytes can be interpreted as another message.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Repeating groups
Groups are sequential flyweight views, not random-access collections:
Rank #3
final OrderEncoder.LegsEncoder legs = order.legsCount(2);
legs.next().instrumentId(1001).quantity(10);
legs.next().instrumentId(1002).quantity(20);
final OrderDecoder.LegsDecoder legsIn = orderIn.legs();
while (legsIn.hasNext()) {
legsIn.next();
long instrument = legsIn.instrumentId();
int quantity = legsIn.quantity();
}
Call next() once for every entry. Skipping that step, or reading group fields out of order, can advance the flyweight incorrectly and corrupt interpretation of following data.
Variable-length data
Strings and byte arrays are encoded with a length prefix and payload. Their exact generated methods depend on the declared length type, encoding and field name; examples may be a string setter accepting a Charset or a putPayload-style byte method. Decide explicitly whether text is UTF-8 or ASCII, enforce a maximum length, and distinguish text from opaque binary data.
Variable data belongs after fixed fields and groups. It reduces the simplicity of random access and can copy bytes from application strings or arrays, so “flyweight” does not mean every operation is zero-copy. Never retain a decoder view after its underlying receive buffer has been reused; copy data that must outlive that buffer.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Schema evolution and compatibility
Preserve existing field, group and data IDs. Do not reuse IDs of deleted members. Keep old fields in their original order and use versioning attributes such as sinceVersion for additions. Test both directions:
Rank #4
- new writer to old reader;
- old writer to new reader;
- all supported enum and null cases.
sbe.schema.transform.version can generate an older schema view for compatibility testing. Golden encoded messages shared across Java and other language implementations are especially valuable for validating widths, signedness, byte order, alignment, headers and version semantics.
Unknown enum values require an explicit policy. The tool exposes sbe.decode.unknown.enum.values; the resulting behavior depends on configuration and generated code, so test it rather than assuming an exception or a null mapping.
Do not confuse three cases: a field absent because the reader predates it, an encoded null sentinel, and a legitimate business value equal to a default. Java null is not itself an SBE wire value.
Correctness rules that prevent silent corruption
- Access order: process fields, groups and variable data in schema order. Development builds can enable
-Dsbe.generate.access.order.checks=trueand Java runtime precedence checks with-Dsbe.enable.precedence.checks=true; measure their production cost. - Buffer capacity: account for header, fixed fields, every group entry and variable payload. Reject oversized data instead of truncating it.
- Header validation: check schema ID, template ID, block length, acting version and message boundaries before reading.
- Endianness: producers and consumers must agree on the schema byte order and primitive representation.
- Ownership: generated views are generally not immutable, thread-safe objects. Define who owns the buffer and when it may be reused.
- Unknown values: handle newer enum members and unsupported versions deliberately.
Benchmarking Java SBE fairly
Use JMH with warm-up and separate encode, decode, allocation and end-to-end tests. Include fixed-only messages, groups and variable data. Report throughput and latency distributions such as p50 and p99, not just one average. Bounds checks, precedence checks, string conversion, logging and transport behavior can dominate the codec itself. Compare SBE with a correctly optimized implementation of the alternative format on the same hardware and workload.
SBE compared with common alternatives
| Format | Good fit | Trade-off versus SBE |
|---|---|---|
| JSON | Human-readable APIs and configuration | Larger text and typically more parsing/allocation work |
| Java serialization | Legacy Java-only persistence | Weak interoperability and a problematic security history |
| Protocol Buffers | General cross-language RPC and events | More flexible abstraction than a tightly laid-out codec |
| FlatBuffers | Low-copy access across many languages | Different schema and API trade-offs |
| FIX/FAST | Financial messaging ecosystems | Specialized semantics and operational context |
| Custom binary | Maximum bespoke control | Higher maintenance and interoperability burden |
When Java SBE is the right choice
Choose it when predictable latency, compact messages, controlled schemas, generated multi-language codecs and direct-buffer access matter more than arbitrary nesting or human readability. It is a strong candidate for market data, orders, telemetry and high-rate event streams, especially where a team can enforce generation and compatibility tests.
Prefer a simpler or more flexible format when messages are dynamic, schemas are loosely governed, browser or external-client interoperability dominates, operators need to inspect payloads manually, or ordinary CRUD traffic does not justify SBE’s ordering and lifecycle rules.
Before adopting SBE, answer yes to most of these questions: Are latency targets explicit? Can schema changes be reviewed centrally? Will CI generate and compile codecs? Can the team test old/new readers and writers? Can it accept binary debugging and explicit buffer ownership?
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

