japes¶
Java Archetype-based Parallel Entity System — a high-throughput ECS for the JVM with first-class change detection, Flecs-style entity relations and a tier-1 bytecode generator that turns your system methods into direct-dispatch hidden classes.
Pre-release
The API is stable enough to benchmark but reserves the right to change before 1.0. Snapshot Maven artifacts are published from main to GitHub Packages — see Installation for the client-side wiring.
What japes is¶
record Position(float x, float y) {}
record Velocity(float dx, float dy) {}
class Physics {
@System
void integrate(@Read Velocity v, @Write Mut<Position> p) {
var cur = p.get();
p.set(new Position(cur.x() + v.dx(), cur.y() + v.dy()));
}
}
var world = World.builder().addSystem(Physics.class).build();
world.spawn(new Position(0, 0), new Velocity(1, 1));
world.tick();
Everything is declarative. Components are plain records. Systems are annotated methods whose parameters tell the scheduler exactly what they read and write, so the DAG builder can run disjoint systems in parallel automatically — no manual locking, no priority tables. The scheduler then emits a hidden class per system: your user method is called via direct invokevirtual with every argument hoisted into a JIT register, so hot loops inline as if you'd hand-written one big monolithic method.
Feature grid¶
Archetype storage¶
Flat chunked arrays keyed by component signature. Every matching archetype iterates cache-linearly with zero type-based dispatch in the hot loop.
Tier-1 bytecode dispatch¶
Per-system hidden classes generated via java.lang.classfile. The JIT sees an ordinary virtual call and inlines your whole system body into the chunk loop.
Change detection¶
@Filter(Added.class) / @Filter(Changed.class) filters and RemovedComponents<T> service params, backed by per-component dirty lists — observers walk only entities that actually changed.
First-class relations¶
@Relation, @Pair(T.class), @ForEachPair(T.class) with non-fragmenting forward + reverse indices and archetype markers — Flecs-style without leaving Java.
Deferred structural edits¶
Commands buffers spawn/despawn/insert/remove operations from inside parallel systems and flushes them at stage boundaries — no locking, no race conditions.
Disjoint-access parallelism¶
The scheduler analyses each system's access set statically and runs everything that commutes on the multi-threaded executor — no annotations, no priorities.
Headline benchmark. With SoA storage, iterateWithWrite at 10k lands at japes 1.61 µs/op vs Bevy 0.15's 6.28 µs/op — 3.9× faster than the Rust reference on writes. Change detection stays strong: SparseDelta — data pending. The benchmarks section shows the full cross-library tables plus the predator/prey relations workload where data pending for 500 × 2000 tuples.
Where to start¶
I just want to ship code¶
Quick start → gradle dependency, first world, first system, first tick.
I want to learn the whole API¶
Tutorials → 22 chapters covering every annotation and service parameter, from components to relations.
I want the numbers¶
Benchmarks → methodology, per-benchmark analysis and the cross-library cost-model breakdown.
License¶
MIT. japes is single-author hobby research released in the hope it's useful. Contributions, issues and pull requests all welcome at github.com/zzuegg/japes.