Systems language · AOT · LLVM · self-hosted
A single-threaded, ahead-of-time language in the Java family — not a subset of it. No VM, no JIT, no garbage collector. Familiar classes, generics and exceptions; native speed and arena-scoped memory underneath.
// Looks like Java — runs with no GC.
public class Report {
public static void main(String[] args) {
int total = 0;
arena scratch { // scoped memory
int[] rows = new int[1<<16];
for (int i = 0; i < rows.length; i++)
total += (rows[i] = i * 3);
} // freed here — O(1), no pause
System.out.println(total);
}
}
The thesis
SuperJ compiles to LLVM IR and then to machine code. There is no bytecode, no class loading, no tracing collector, and no threading — the whole program is known at compile time, so behavior is predictable down to the allocation.
A global arena for the program, plus lexical arena {} blocks reclaimed in one O(1) drop — no stop-the-world pauses.
Straight to optimized machine code. No VM, no JIT warm-up, no runtime to ship.
Threads, locks, monitors and the memory model are gone — deterministic by construction.
The SuperJ compiler is written in SuperJ — the toolchain builds itself, end to end. We dogfood our own language.
Signature feature
Allocate short-lived objects inside an arena block; when the block exits, the whole arena is dropped at once. A reference that would outlive its arena is a compile error, not a lurking use-after-free.
Node createNode(int v) {
return new Node(v); // global arena — safe to return
}
void process() {
arena temp {
Buffer buf = new Buffer(1024); // in temp
Node n = createNode(5); // in global
// outer = buf; ← rejected: escapes its arena
} // temp dropped: buf freed, n still valid
}
Lexical, not dynamic. A new belongs to the arena it's written inside — called methods keep using the global arena unless they open their own.
↳ n (global arena) survives the block.
Systems reach
Beyond the arena model, SuperJ adds the primitives you'd otherwise drop to C for — with the type system still watching your back.
arena {} for O(1) bulk reclaim; local for stack-scoped references.
First-class i128, i256, i512 primitives for crypto and big-int math.
Header-free value types with a known wire layout — ideal for protocols and mmap.
int[,] — contiguous, stride-indexed, a distinct type from jagged int[][].
native methods call straight into the C ABI — no JNI, no marshalling layer.
Class::method targets a single-abstract-method interface — capture-free, no closures.
Class- and method-level, bounded params, and ? extends / ? super wildcards.
Portable vector families (Byte64, Float8, …) lowered to native SIMD IR.
A local read before it's assigned is a compile error — no accidental garbage reads.
The trade
Every removal buys predictability; everything kept is what made Java productive in the first place.
synchronized, volatilefinalize()String / string, one immutable typeProof
A web server on the built-in HTTP stack, compiled to a single native binary and load-tested over loopback — the server pinned to one core, the load generator to another. It serves faster than wrk can issue requests.
Measured on a Ryzen 9 9950X3D, single core each (server on CPU 4, client on CPU 3): SuperJ's own pipelined client reaches ~515K req/s while wrk tops out at ~423K — the load generator, not the server, is the limit. Under sustained load the server's tail stays flat — p50 156µs, p99 167µs — because there's no collector to pause on. See the full benchmarks →
One line, the whole idea