Generation of constantly-sized flyweight accessors to Chronicle Bytes and simple bean-style on-heap implementations from interfaces. Interfaces that can be processed by Chronicle-Values generation are called value interfaces.
Project status: Stable - the feature matrix (see below) is very vast and not expected to be implemented further. Please write the value interface according to the specification below, with unit tests for your interface. If the generation from the value interface (according to spec) doesn’t work, please report the case via GitHub issues.
All classes in the package net.openhft.chronicle.values.internal and its subpackages are internal implementation details. They may change without notice and must not be referenced directly.
Value interfaces must belong to a non-empty package (they cannot sit in the default package).
package test; interface Balance { long getDollars(); void setDollars(long dollars); long addDollars(long addition); int getCents(); void setCents(int cents); }The above is compiled into either a 12-byte flyweight or a regular bean with long dollars and int cents.
Must be annotated with @MaxUtf8Length:
interface Client { CharSequence getName(); void setName(@MaxUtf8Length(20) CharSequence name); CharSequence getStateCode(); void setStateCode(@NotNull @MaxUtf8Length(2) CharSequence stateCode); }The value supplied to @MaxUtf8Length is the allowed size once the text is encoded as UTF-8. The native form checks this limit when writing to the backing BytesStore. Heap implementations assume the caller supplies a compliant value and any breach is detected only when copied to a native instance.
Allows nested structures:
interface Point { double getX(); void setX(double x); double getY(); void setY(double y); } interface Circle { Point getCenter(); void getUsingCenter(Point using); void setCenter(Point center); double getRadius(); void setRadius(double radius); }(Self-references are forbidden.)
interface Order { enum State { NEW, CANCELLED, FILLED } State getState(); void setState(@NotNull State state); }The generated classes keep a reference to the array of constants for each enum field. The Enums helper obtains this array via reflection from EnumSet.getUniverse(Class). Caching the array lets the marshalling code translate ordinals without calling values() on every access.
[get]FieldName[At], [set]FieldName[At], or isFieldName for boolean fields. You may omit the get/set prefixes:
interface Point { double x(); void x(double x); double y(); void y(double y); }type addAtomicFieldName[At]([int index, ]type addition) Atomic variant for numeric primitives.
boolean compareAndSwapFieldName[At]([int index, ]type expected, type newValue) Works for primitives, enums, and Date.
Fields are laid out group by group. Use @Group to cluster fields and control their ordering. Fields without @Group form the default group, which always comes first:
interface Complex { @Group(1) double real(); void real(double real); @Group(2) double imaginary(); void imaginary(double imaginary); }enum and string fields are nullable by default; mark with @NotNull to forbid null:
interface Instrument { CharSequence getSymbol(); void setSymbol(@NotNull @MaxUtf8Length(5) CharSequence symbol); }When a field is nullable the generated native form stores a marker instead of the text. Heap implementations use an extra boolean for CharSequence fields to track a null value. With @NotNull the setters emit a NullPointerException if given null.
Annotate with @Range(min=, max=) to reduce flyweight size:
interface Transaction { int getSecondFromDayStart(); void setSecondFromDayStart(@Range(min = 0, max = 24 * 60 * 60) int secondFromDayStart); }// Flyweight Point offHeapPoint = Values.newNativeReference(Point.class); ((Byteable) offHeapPoint).bytesStore(bytesStore, offset, 16); offHeapPoint.setX(0); offHeapPoint.setY(0); // On-heap Point onHeapPoint = Values.newHeapInstance(Point.class); onHeapPoint.setX(1); onHeapPoint.setY(2);Generated classes implement:
-
Copyable<Point>- e.g.onHeapPoint.copyFrom(offHeapPoint) -
BytesMarshallable(Chronicle-Bytes) -
Correct
equals,hashCode,toString -
Byteable(no-op on the heap implementation)
The Copyable feature allows an on-heap value to take a snapshot of a native instance or vice versa. This provides a simple way to shuttle data between the two representations.
You may extend these in the interface to avoid casting:
interface Point extends Byteable, BytesMarshallable, Copyable<Point> { ... } Point offHeapPoint = Values.newNativeReference(Point.class); // no cast required offHeapPoint.bytesStore(bytesStore, offset, offHeapPoint.maxSize());Chronicle-Values empowers you to work with structured data with high performance and type safety, especially when interfacing with low-latency and off-heap memory systems. It achieves this by generating efficient data accessors from Java interfaces.
Chronicle-Values is designed to provide:
-
High Performance & Low Latency: Access and manipulate data with minimal overhead, crucial for systems where every microsecond counts. This is particularly true when using its "native" (off-heap) implementations.
-
Minimized GC Impact: Through the use of off-heap 'flyweight' objects, which act as lightweight views onto raw byte data. This significantly reduces garbage collection pressure by avoiding the creation of numerous heap objects.
-
Type Safety: Define your data structures using standard Java interfaces. This provides compile-time checking, clear API contracts, and reduces runtime errors.
-
Developer Convenience: The library automatically generates the necessary accessor boilerplate (getters, setters, etc.) based on your interface definition and intuitive annotations. This saves development time and reduces manual coding errors.
-
"Zero-Deserialization" Access: Read data directly from memory without the traditional cost of hydrating full heap objects, allowing for faster processing.
-
Seamless Integration: Designed to work smoothly with other Chronicle libraries like Chronicle Map (for off-heap key-value stores) and Chronicle Queue (for low-latency messaging), enabling efficient data storage and exchange.
Chronicle-Values is ideal when you need to work with data that has a fixed, well-defined structure at compile time. Common scenarios include:
-
Representing financial messages (e.g., FIX, SBE, or custom binary protocols).
-
Defining event payloads for event-sourcing architectures.
-
Creating complex, fixed-layout keys or values for use with Chronicle Map or Chronicle Queue.
-
Any situation where you need performant, typed access to structured binary data, whether on-heap or off-heap.
Chronicle-Values operates on top of Chronicle-Bytes, which provides the foundational layer for byte manipulation. While Values offers a higher-level, typed abstraction for structured data, Chronicle-Bytes remains essential for:
-
Low-level, direct manipulation of byte sequences.
-
Implementing custom serialization or deserialization logic for arbitrary formats.
-
Parsing and constructing binary network protocols from scratch.
-
Handling dynamic, unstructured, or schema-less binary data.
Typical Workflow: A common pattern is to use Chronicle-Bytes for initial I/O operations (e.g., reading from a network socket or a file) or to parse the outer envelope of a raw data stream. Once you’ve identified a segment of that stream that corresponds to a known, fixed structure defined by a value interface, you can then map a Chronicle-Values native reference (flyweight) over that region for typed, convenient, and performant access.
For every value interface, Chronicle-Values can generate two types of implementations:
-
Native (Flyweight) References (
Values.newNativeReference(..)):-
These are lightweight views onto a
BytesStore(which can be on-heap or off-heap memory). -
They provide maximum performance and are central to off-heap data strategies.
-
They do not store data themselves; they merely provide typed accessors to the underlying bytes.
-
Careful management of the backing `BytesStore’s lifecycle is crucial (see section on Lifecycle Management).
-
-
Heap Instances (
Values.newHeapInstance(..)):-
These are standard Java objects (POJOs) that store their data on the Java heap.
-
Useful for interacting with other parts of your system that expect POJOs, or when off-heap performance is not the primary concern for a particular data structure.
-
Data can be easily copied between native and heap instances using the generated
copyFrom()method (from theCopyableinterface).
-