One benefit of this approach was that by using the interface as the type you could fairly easily support a flyweight pattern, reducing GC pressure when working with large off-heap collections. The parallels between stateless interfaces and offheap structs was also quite pleasing.
I'd love to see a similar effort using more modern techniques than Unsafe et al.
I understand the issue about using Layout and MemorySegment being verbose but the reason I'm using those things it to develop high performance software that uses off-help memory and bypasses object allocation.
What does "map Java record types onto native memory" actually mean? Did you somehow turn a Java record into a flyweight or is `Point point = points.get(0);` just instantiating a record instance using data read from off-help memory? If it's a dynamic mapping library using reflection, that's cool but doesn't it kill the performance goals for most Java off heap usage?
Is this more of a off-heap to heap bridge for pulling data into the normal Java space when performance isn't critical?
Typed off-heap memory for Java 25 and greater.
TypedMemory is a Java library for working with contiguous off-heap memory through strongly typed views. It builds on the Java Foreign Function & Memory (FFM) API and lets you map Java record types onto native memory with a simple, expressive API.
Instead of manually managing layouts, offsets, and low-level access patterns for every structure, TypedMemory gives you a type-safe abstraction over memory while still preserving the low-level control needed for systems, interop, graphics, simulation, and data-oriented programming.
import module com.mamba.typedmemory;
record Point(float x, float y) {}
void main() {
try (Arena arena = Arena.ofConfined()) {
Mem<Point> points = Mem.of(Point.class, arena, 10);
points.set(0, new Point(5, 3));
Point point = points.get(0);
IO.println(point);
}
}
Working directly with raw memory in Java is powerful, but often verbose and repetitive.
TypedMemory aims to make off-heap programming feel more natural by providing:
This makes it useful for:
Arenaget(index) / set(index, value)MemoryLayoutMemorySegmentsTypedMemory is currently experimental.
The core API is already usable, but the project is still evolving and may introduce breaking changes as the design is refined.
Implemented:
Planned features to implement:
long addresses manuallyjava --enable-native-access=ALL-UNNAMED -jar app.jarjava --enable-native-access=your.module.name -m your.module.name/com.example.MainTypedMemory is built with Maven and targets Java 25.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>25</maven.compiler.release>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
</plugin>
</plugins>
</build>
Compile the library:
mvn clean compile
Run tests:
mvn test
Build the jar:
mvn clean package
Install TypedMemory into your local Maven repository:
mvn clean install
TypedMemory is available from Maven Central, so you can add it directly to your project's pom.xml:
<dependency>
<groupId>io.github.mambastudio</groupId>
<artifactId>typedmemory</artifactId>
<version>0.1.0</version>
</dependency>
If your application uses the Java module system, add this to module-info.java:
requires com.mamba.typedmemory;
import module com.mamba.typedmemory;
record Color(float r, float g, float b, float a) {
Color(float r, float g, float b) {
this(r, g, b, 1.0f);
}
}
void main(){
try (Arena arena = Arena.ofConfined()) {
Mem<Color> colors = Mem.of(Color.class, arena, 3);
colors.set(0, new Color(1f, 0f, 0f));
colors.set(1, new Color(0f, 1f, 0f));
colors.set(2, new Color(0f, 0f, 1f));
Color c = colors.get(1);
IO.println(c); // Color[r=0.0, g=1.0, b=0.0, a=1.0]
}
}
import module com.mamba.typedmemory;
record Pixel(int i, int j) {}
record Point(byte x, @size(3) Pixel[] y, @size(3) int[] z) {}
void main(){
try (Arena arena = Arena.ofConfined()) {
Mem<Point> points = Mem.of(Point.class, arena, 10);
points.set(0, new Point(
(byte) 7,
new Pixel[] { new Pixel(1, 2), new Pixel(3, 4), new Pixel(5, 6) },
new int[] { 10, 20, 30 }
));
Point p = points.get(0);
IO.println(p);
}
}
TypedMemory preserves the underlying memory layout, making it easier to inspect and reason about the actual structure stored off-heap.
try (Arena arena = Arena.ofConfined()) {
Mem<Color> colors = Mem.of(Color.class, arena, 4);
IO.println(colors.layout());
}
This is especially useful when:
TypedMemory can also create typed views over an existing MemorySegment.
MemorySegment segment = ...;
Mem<Color> colors = Mem.wrap(Color.class, segment);
This is useful when memory comes from:
Typical operations include:
Mem<T> mem = Mem.of(MyRecord.class, arena, count);
mem.get(index);
mem.set(index, value);
mem.fill(value);
mem.init(i -> ...);
mem.copyTo(other);
mem.copyFrom(other);
mem.swap(i, j);
mem.segment();
mem.layout();
mem.size();
mem.type();
TypedMemory is not trying to replace the FFM API.
Instead, it sits one level above it:
The goal is to make low-level Java memory programming feel typed, direct, and practical.
Records provide a natural schema-like model for structured memory.
They offer:
TypedMemory uses this to bridge Java data definitions and low-level memory representation.
Coming soon.
TypedMemory is especially relevant for:
The following are the limitations
Feedback, issues, and suggestions are welcome.
If you are interested in:
then contributions and discussion are highly appreciated.
GitHub: mamba-studio/TypedMemory
TypedMemory is licensed under Apache License 2.0