Features

What SuperJ gives you

SuperJ keeps the parts of Java that make it pleasant and productive, drops the parts that fight predictable native performance, and adds a layer of systems-level capability Java doesn't have. The result reads like Java but behaves like C.

The headline feature

AI-native development — a language built for agents that write code

Every design decision in SuperJ — the Java syntax, the deterministic execution, the claim layer, the self-hosted compiler — serves one thesis: an AI agent that writes code needs a language that makes wrong code either impossible, caught at compile time, or trivially reproducible and fixable. SuperJ is engineered end-to-end for that. Here are the five key enablers:

  • enabler 1

    Java syntax — LLMs are already trained on it

    SuperJ is Java-shaped: classes, generics, exceptions, method references. Every LLM trained on public code already knows the syntax. An agent writes correct SuperJ on the first try — the deltas (arena blocks, local, no lambdas) are small, listed in one scannable page, and documented in the agent guide. No new syntax to learn, no fine-tuning required.

  • enabler 2

    Deterministic behavior — agents can reason confidently

    Single-threaded execution, arena memory, no GC pauses, no JIT deoptimization, no reflection. The program that runs today is the program that runs tomorrow — byte-for-byte. When an agent's code is wrong, the failure is reproducible: same input, same output, same crash, every time. No heisenbugs, no race conditions, no "works on my machine." Determinism is the strongest correctness property an agent can have — every bug is reproducible and fixable, not just one class of bug prevented.

  • enabler 3

    Claim layer — immediate AI harness

    Capabilities (net, fs.read), architecture rules (import boundaries), and contracts (pure, noalloc, requires, ensures) — all compiler-enforced, zero runtime cost in release. An agent can't go rogue: if it writes network code in a package that holds no net capability, the compile fails. The claim layer is the guardrail that lets you hand an agent the keys and know exactly what it can and cannot do. See The Claim Layer.

  • enabler 4

    The compiler itself is the AI harness

    The superj compiler is comprehensive, fast, and self-hosted — built in SuperJ, not a foreign toolchain. It catches wrong code at compile time: type errors, arena escape, uninitialized locals, missing capabilities, contract violations. Every diagnostic is located and actionable. The compiler is the agent's pair programmer: it stops misbehavior before the code ever runs. And because it's self-hosted, the agent can read, modify, and extend the compiler itself — the toolchain is not a black box.

  • enabler 5

    Agent guide in the tree + reproducible build

    Every distribution ships AGENTS.md plus a topic-graph of focused agents/*.md files (types, memory, classes, SIMD, native, SDK, build, gotchas) — the same material a human contributor reads, written for both. The build is whole-program and reproducible: superj build from the same source always produces the same binary. An agent can scaffold a project, write a handler, wire up the SDK, compile to native, run tests, and verify the output — all without a human typing a line.

Why this is the headline. For seventy years, language design asked what makes a human programmer happy. That assumption has broken. What does a language look like when its primary user is a machine that is confidently, plausibly, and frequently wrong — and why does Rust, the strongest "looks right but isn't" detector ever built, paradoxically make agents struggle? The answer is: agents need legibility (Java syntax they already know), reproducibility (determinism so bugs are reproducible), and guardrails (the claim layer so they can't misbehave). SuperJ is engineered for exactly that. Read the full argument: The Pursuit of Agentic Happiness

No VM. No JIT. No surprises.

Why SuperJ

Extreme development speed, at or exceeding C performance

The core promise: write at Java speed, run at C speed — or faster. No JVM warm-up, no GC pauses, no JIT deoptimization, no borrow-checker tax. A single self-contained native binary from the same source a Java developer already knows how to read. Across 54 head-to-head benchmarks, SuperJ wins or ties 78% — and beats C by up to 2.57× on SIMD matmul, 10.4× on i512 division, and 7× on adversarial hash-map keys. That's the floor: native performance is the baseline, not the ceiling.

78%
of 54 benchmarks vs C — wins or ties
515K
req/s on the HTTP server — wrk is the bottleneck, not the server
11.7×
faster than Java on inverted-index search
  • repl

    Built-in REPL

    A JIT-backed read-eval-print loop (LLVM ORC JIT host) for exploring expressions, testing SDK calls, and prototyping handlers interactively. superj repl — evaluate a snippet, see the result, no compile-link cycle.

  • ide

    IntelliJ IDEA plugin

    Syntax highlighting, Go-to-Declaration, and run configuration — shipped under plugins/intellij/. Develop SuperJ in the IDE you already use; the plugin is optional but there from day one.

terminal
$ superj repl
superj> i256 x = 6i256;
superj> x * x + 1i256
res0 = 37
superj> Hash.sha256("hello")
res1 = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
superj> arena t { int[] a = new int[1024]; System.out.println(a.length); }
1024

Write at Java speed. The syntax is Java — classes, generics, exceptions, method references — so a Java developer (or an LLM trained on Java) is productive on day one. The REPL and the IntelliJ plugin mean the inner dev loop is instant. The agents/ topic graph is the same material a human contributor reads — an LLM with repo access can scaffold a project, write a handler, wire up the SDK, and compile to native without a human typing a line of tutorial. Run at C speed. AOT to LLVM -O3, arena memory with no GC pauses, and first-class SIMD/wide-integer/auto-vectorization primitives put SuperJ at or above C across the benchmark suite. That's the whole idea: reads like Java, behaves like C — hence super Java. Get started →

Memory

Arena memory — deterministic, no collector

No tracing garbage collector. new allocates from an arena. A global arena lives for the whole program; lexical arena {} blocks are reclaimed in one O(1) drop when the block exits — no scan, no pause. A reference that would outlive its arena is a compile error, not a use-after-free.

arena.sj
Node createNode(int v) {
  return new Node(v);   // global arena — safe to return
}

void process() {
  arena temp {
    Buffer buf = new Buffer(1024);  // in temp
    // outer = buf;  ← compile error: escapes its arena
  }              // temp dropped: buf freed, O(1)
}

void stack() {
  local Point p = new Point(1,2); // stack-allocated
}
  • global arena

    Default allocation

    A new outside any arena block allocates from the global arena — safe to return, store, hand to C. Reclaimed by the OS on process exit.

  • arena blocks

    Scoped & checked

    arena temp { … } — dropped at block exit. Escape is a compile error, statically checked. Lexical, not dynamic.

  • local

    Stack allocation

    local Point p = new Point(...) lowers to alloca — for the hot, bounded case you opt into.

  • no destroy()

    Arena drop is the reclamation

    No finalize(), no destroy(). File handles close(), crypto keys zeroize(), DirectArray free() — the rest is arena drop.

Backend

AOT to native — no VM, no JIT, no runtime to ship

SuperJ compiles to LLVM IR and then to a single self-contained native binary. No bytecode, no class loading, no JIT warm-up. Full speed from request one. The compiler is entirely built by SuperJ itself — we dogfood our own toolchain.

  • llvm

    Optimized machine code

    Straight to -O3 native code through LLVM 22. Optional --enterprise whole-program LTO across SDK + user code.

  • self-hosted

    Compiler in SuperJ

    The superj binary is produced by SuperJ — the toolchain builds itself, end to end.

  • targets

    macOS & Linux

    macOS arm64 (kqueue), Linux x86_64 and aarch64 (epoll). One binary per target — copy and run.

  • flags

    Tune the codegen

    --no-bounds-check, --simd=avx2, --target-cpu=native, --debug. The max-perf recipe is one line.

Concurrency model

Single-threaded by design — scale with processes

Threads, locks, synchronized, volatile, and the Java memory model are gone. One event loop, one thread, one causal story — deterministic by construction. Scale across cores by running more processes on SO_REUSEPORT; coordinate across processes with the SEDA sequencer's total-order event stream.

scale.sj
// one process, one core — scale by running more copies:
//   for i in 1 2 3 4; do ./webserver 8080 & done
// the kernel balances connections across them (SO_REUSEPORT)

public class WebServer {
  public static void main(String[] args) {
    NioConfig cfg = new NioConfig(..., true, ...);
    NioAdapter a = new NioAdapter(cfg);
    a.open("127.0.0.1", 8080, provider);
    while (true) { a.poll(0); }  // one loop, one thread
  }
}
  • no locks

    No data races

    One thread means no locks, no atomics in user code, no cross-core cache ping-pong on the hot path.

  • determinism

    Replay is bit-for-bit

    Same event sequence → same state. Bugs reproduce. Tests aren't timing-dependent. The SEDA sequencer is the single ordering authority.

  • SEDA

    Total-order events

    Apps own their state; a single Sequencer drains command queues, stamps a monotonic seq, writes one event queue. Consistency is a property of the sequence, not the scheduler.

  • the math

    Three impossibility results

    Undecidable deadlock freedom, FLP, CAP — the trade is not avoidable. SuperJ pays it upfront in one visible place instead of across thousands of hidden lock acquisitions.

Systems reach

Low-level control Java keeps out of reach

Beyond the arena model, SuperJ adds the primitives you'd otherwise drop to C for — with the type system still watching your back.

  • local

    Stack allocation

    The local keyword lowers new to alloca — the object lives on the stack, zero heap allocation. For the hot, bounded case you opt into: scratch buffers, hash accumulators, per-call contexts. Paired with arena blocks, a request handler can serve with zero allocation on the hot path. No GC pause, no allocation pressure, no escape analysis guessing.

  • layout

    Fixed-layout structs

    Header-less value types with a known wire layout. view(buf, off) flyweight over bytes — zero-copy protocol code.

  • arrays

    Rectangular arrays

    int[,] / int[,,] — contiguous, stride-indexed, a distinct type from jagged int[][].

  • interop

    Native C / Rust

    native methods call straight into the C ABI — no JNI, no marshalling layer. Direct symbol resolution at link time.

  • strings

    UTF-8 by construction

    One string/String type, byte[]-backed, length-prefixed and NUL-terminated — a valid C string zero-copy.

Crypto-grade numerics

Wide integers and SIMD — first-class, not a library

Modern cryptography, big-int math, and numeric kernels need primitives Java simply doesn't have. SuperJ ships them as native types and keywords — lowered by LLVM to the same machine instructions a C compiler emits, then auto-vectorized on top.

crypto.sj
// i128 / i256 / i512 — signed native primitives, not structs
i256 x = 6i256;
i256 y = x * x + 1i256;
i256 q = y / 3i256;          // strength-reduced to limb udiv (#1638)

// secp256k1 scalar arithmetic lives here — one i256 mod-n
// is a single LLVM sdiv, not a 4-limb hand-rolled loop.

local byte[] h = new byte[32];   // stack — no heap alloc
Hash.sha256(msg, 0, msg.length, h, 0);

// SIMD — no new syntax, just typed arrays
float[4] a = ..., b = ..., c = new float[4];
Simd.addFloat4(a, 0, b, 0, c, 0);   // NEON / AVX2 / SSE2
  • i128 / i256 / i512

    Native wide integers

    First-class signed primitives — not library structs. Arithmetic lowers to native LLVM add/mul; division by a constant is strength-reduced to limb udiv + umulh. Essential for modern crypto: secp256k1, AES-GCM, EIP-712, SHA-3 all operate on 256-bit values natively. i256 general division is 3.4× faster than C; i512 division is 10.4× faster; i512 divide-by-constant is 1483× faster — clang still calls __divti3, SuperJ emits the strength-reduced limb sequence.

  • SIMD

    First-class vector intrinsics

    Portable vector families (Byte16, Float4, Float8, Double2, …) lowered to native SSE2 / AVX2 / NEON IR — no new syntax, just typed arrays. Simd.addFloat4, Simd.fmaFloat8, Simd.dotFloat8 — arithmetic, bitwise, compare, masked blend, convert, reduce, gather/scatter, dot, prefix-sum. On ARM NEON is baseline and always on; on x86 select --simd=sse2|avx2.

  • complex

    Complex numbers

    First-class cdouble (128-bit) and cfloat (64-bit) primitives — two floats packed as one type. Arithmetic (+ - * /), ==/!=, and a full ComplexMath SDK class (exp, log, sqrt, sin/cos/tan, abs, arg, conj, …) over C99 <complex.h>. Imaginary literals: 3.0i, 2.5fi.

  • auto-vec

    Auto-vectorization on top

    Even scalar loops get vectorized. LLVM -O3 auto-vectorizes the SuperJ IR directly: the HNSW byte-L2 distance loop compiles to usubl.8h/smlal.4s/ldp q NEON (32 bytes per iteration) with no explicit intrinsics. A cache-blocked tiled GEMM with local float[4] accumulators beats C's auto-vectorizer by 1.15-2.57× at every matrix size — register-resident accumulators give both register reuse and cache locality, while C's streaming approach gets only one.

Why it matters. A language that wants to do crypto and numeric kernels at native speed needs these primitives at the type-system level, not as a library. Java's BigInteger allocates per operation and boxes every value; Rust's u256 is a library struct with method-call dispatch. SuperJ's i256 is an LLVM IR type — the backend decomposes it into 2×128-bit GPRs or AVX-512 zmm registers, and the optimizer treats it like any other integer. That's why the wide-integer benchmarks match C on add/mul and beat it by 3-1483× on division.

GPU & AI

GPU compute and LLM inference — first-class, not a foreign call

The sj.gpu stack puts Metal, CUDA, and a CPU reference backend behind one API — same code, same results. Load a GGUF model, prefill, decode: forty lines, faster than llama.cpp on Apple Silicon.

  • gpu

    sj.gpu — Metal / CUDA / CPU

    Open a GpuDevice, load a quantized model (Model.load), run prefill + decode with a KvCache. Metal on Apple Silicon, CUDA on NVIDIA, and a CPU reference backend everywhere else — identical code, bit-for-bit results. See Writing an LLM Inference Engine.

  • tensor

    Tensor layer for custom architectures

    Beneath the high-level API: a Tensor layer for custom model architectures — quantized matmul, attention, RoPE, all as GPU kernels. The same stack that outruns llama.cpp.

Architecture & contracts

The Claim Layer — compiler-enforced intent

Declare what each package may do (capabilities), what it may import (architecture), and what its methods must guarantee (contracts) — the compiler holds every line to it. Zero runtime cost in release builds.

  • capabilities

    Capabilities — least privilege per package

    One line in Build.sj: capabilities = { "myapp", "net, fs.read" }. Default-deny: any package not listed holds no capabilities. superj capabilities shows granted vs. used — tighten until they match. See The Claim Layer.

  • architecture

    Architecture rules — import boundaries

    Declare which packages may import which — enforce layering at compile time. No more "util depends on everything" rot.

  • contracts

    pure, noalloc, requires, ensures

    One-word method claims: pure (no side effects), noalloc (no allocation). Pre/postconditions with requires/ensures — checked in debug, erased from release binaries.

The trade

A deliberate ledger

Every removal buys predictability; everything kept is what made Java productive in the first place.

✗ Removed from Java

  • // threads, synchronized, volatile
  • // tracing garbage collector
  • // reflection & class loading
  • // lambdas & closures
  • // autoboxing / unboxing
  • // non-static inner classes
  • // checked exceptions, modules, finalize()
  • // switch pattern matching

✓ Kept from Java

  • // classes, interfaces, inheritance
  • // generics with erasure + wildcards
  • // enums & anonymous classes
  • // exceptions (all unchecked)
  • // varargs & method references ::
  • // instanceof pattern matching
  • // familiar control flow & syntax
  • // String / string, one immutable type

SDK

Batteries-included systems SDK

Every package is under sj.*. Discover the full API with superj doc --list and superj doc <class-fqn>.

PackageWhat
sj.langString, StringBuilder, Math, Integer, System
sj.utilcollections & hash, primitive-specialized (IntArrayList, Int2IntMap, ByteSet…), random, base64, bit utils
sj.ioFile, FileReader/Writer, DirectArray, mmap
sj.httpincremental HTTP/1.1 + HTTP/2 server, TLS 1.3, cookies, content types, routing, static files, WebSockets
sj.jsonhand-written incremental JSON parser
sj.sedathe event-driven framework (Apps → Sequencer → event queue)
sj.cryptoSHA256 (ARM NEON), Secp256k1, EthereumAddress, EIP-712, TLS engine
sj.netNioAdapter event loop (TCP/UDP/Unix, epoll/kqueue), UnixGateway
sj.testAsserts, the unit-test harness, golden-output suite

No autoboxing — List<int> is a compile error. Use the primitive-specialized collections for int/long/byte keys and values; the generic ArrayList<E> / HashMap<K,V> for reference types. The SDK links in three variants — community (archive), enterprise (LTO), vip (source) — see Download.

Ecosystem

The linkable ecosystem is the compiled ecosystem

SuperJ is an LLVM language, so the compiled C-ABI core of every LLVM language's ecosystem (Rust, C, C++, Zig, Swift) links via native for free: crypto (ring, BoringSSL, libsodium), compression (zstd, lz4, brotli), numerical kernels (BLAS/LAPACK), parsers, system bindings. The source-ergonomic layer (derive macros, async desugaring) doesn't cross any language boundary — not even to C — and the SuperJ SDK covers the Java-ergonomic gap (collections, JSON, HTTP) so you rarely miss it.

Safety

Determinism is the stronger property

SuperJ doesn't have a borrow checker. The one bug class it makes impossible isn't worth the permanent per-line tax for most software. Instead, single-threaded + SEDA gives you determinism: every bug reproducible and fixable, no timing-dependent behavior, no timing attack surface. Memory safety is a negative property obtained by introducing nondeterminism; determinism closes the larger hole by construction.

Read the memory-safety note →