特性

SuperJ 给你什么

SuperJ 保留 Java 中让人愉悦、高效的部分,丢掉妨碍可预测原生性能的部分,并加入一层 Java 本不具备的系统级能力。结果就是:读起来像 Java,跑起来像 C。

核心特性

AI 原生开发 — 为写代码的 agent 而生的语言

SuperJ 的每一个设计决策 — Java 语法、确定性执行、claim 层、自托管编译器 — 都服务于一个理念:写代码的 AI agent 需要一门让错误代码要么不可能、要么编译期捕获、要么可复现可修复的语言。 SuperJ 端到端地为此而设计。以下是五个关键使能因素:

  • 使能 1

    Java 语法 — LLM 已经训练过了

    SuperJ 是 Java 形状的:类、泛型、异常、方法引用。每一个用公开代码训练的 LLM 都已经认识这套语法。agent 第一次就能写出正确的 SuperJ — 差异点(arena 块、local、没有 lambda)很小,列在一页可扫读的文档里,并在 agent 指南中详细说明。没有新语法要学,不需要微调。

  • 使能 2

    确定性 — agent 可以自信地推理

    单线程执行、arena 内存、没有 GC 停顿、没有 JIT 反优化、没有反射。今天跑的程序就是明天跑的程序 — 逐字节一致。当 agent 的代码出错时,失败是可复现的:同样的输入,同样的输出,同样的崩溃,每次都一样。没有 heisenbug,没有竞态条件,没有"在我机器上能跑"。确定性是 agent 能拥有的最强正确性属性 — 每一个 bug 都可复现可修复,而不只是阻止一个 bug 类。

  • 使能 3

    Claim 层 — 即时的 AI 约束

    能力(netfs.read)、架构规则(导入边界)和契约(purenoallocrequiresensures)— 全部编译期强制,release 构建零运行时开销。agent 无法越权:如果它在没有 net 能力的包里写网络代码,编译会失败。claim 层就是让你放心把钥匙交给 agent、并确切知道它能做什么不能做什么的护栏。参见 Claim 层

  • 使能 4

    编译器本身就是 AI 约束

    superj 编译器全面、快速、自托管 — 用 SuperJ 构建,不是外部工具链。它在编译期捕获错误代码:类型错误、arena 逃逸、未初始化局部变量、缺失能力、契约违规。每一条诊断都是定位明确、可操作的。编译器是 agent 的结对编程伙伴:在代码运行之前就阻止不当行为。而且因为自托管,agent 可以阅读、修改和扩展编译器本身 — 工具链不是黑箱。

  • 使能 5

    仓库内置 agent 指南 + 可复现构建

    每一份发行版都附带 AGENTS.md 以及一组按主题切分的 agents/*.md 文件(类型、内存、类、SIMD、native、SDK、构建、坑点)— 也是人类贡献者要读的材料,为两者同时而写。构建是全程序且可复现的:从同一份源码 superj build 总是产出同一个二进制。agent 可以搭起项目、写处理器、接上 SDK、编译成原生代码、跑测试、验证输出 — 全部无需人类敲一行。

为什么这是核心特性。 七十年来,语言设计问的是怎样让人类程序员开心。这个假设已经失效了。当一门语言的主要用户是一台自信地、貌似合理地、频繁地犯错的机器时,这门语言应该长什么样 — 为什么 Rust,这个有史以来最强的"看起来对但其实不对"检测器,反而让 agent 举步维艰?答案是:agent 需要可读性(已经认识的 Java 语法)、可复现性(确定性让 bug 可复现)、和护栏(claim 层让 agent 不能越界)。SuperJ 正是为此而设计。阅读完整论述:追求 agent 的幸福

没有 VM。没有 JIT。没有意外。

为什么是 SuperJ

极致的开发速度,匹敌甚至超越 C 的性能

核心承诺:用 Java 的速度写代码,用 C 的速度跑代码 — 甚至更快。没有 JVM 预热,没有 GC 停顿,没有 JIT 反优化,没有借用检查器的负担。从 Java 开发者已经会读的同一份源码,产出一个自包含的原生二进制。在 54 项正面交锋的基准测试中,SuperJ 赢或平 78% — 在 SIMD 矩阵乘法上比 C 快最多 2.57×,在 i512 除法上快 10.4×,在对抗性哈希表键上快 7×。这只是地板:原生性能是基线,不是上限。

78%
54 项与 C 对比的基准 — 赢或平
515K
HTTP 服务器 req/s — 瓶颈是 wrk,不是服务器
11.7×
倒排索引搜索比 Java 快
  • repl

    内置 REPL

    一个基于 JIT 的读取-求值-打印循环(LLVM ORC JIT 宿主),用于探索表达式、测试 SDK 调用、交互式地原型化处理器。superj repl — 求值一段代码,看结果,无需编译-链接循环。

  • ide

    IntelliJ IDEA 插件

    语法高亮、跳转到声明、运行配置 — 随 plugins/intellij/ 一并发布。在你已经在用的 IDE 里开发 SuperJ;插件是可选的,但从第一天就准备好了。

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

用 Java 的速度写。 语法就是 Java — 类、泛型、异常、方法引用 — 所以 Java 开发者(或用 Java 训练的 LLM)第一天就能产出。REPL 和 IntelliJ 插件让内部开发循环是即时的。agents/ 主题图也是人类贡献者要读的材料 — 一个有仓库访问权的 LLM 可以搭起项目、写处理器、接上 SDK、编译成原生代码,无需人类敲一行教程。用 C 的速度跑。 AOT 到 LLVM -O3、没有 GC 停顿的 arena 内存、一等公民的 SIMD / 宽整数 / 自动向量化原语,让 SuperJ 在整套基准测试中达到或超过 C。整个想法就是:读起来像 Java,跑起来像 C — 所以是 super Java开始上手 →

内存

Arena 内存 — 确定性的,没有回收器

没有追踪式垃圾回收器。new 从 arena 分配。全局 arena 存活整个程序;词法 arena {} 块在退出时一次 O(1) 释放 — 无扫描,无停顿。一个引用如果生命周期会超出它所在的 arena,就是编译错误,而不是 use-after-free。

arena.sj
Node createNode(int v) {
  return new Node(v);   // 全局 arena — 可以返回
}

void process() {
  arena temp {
    Buffer buf = new Buffer(1024);  // 在 temp 中
    // outer = buf;  ← 编译错误:逃逸出它的 arena
  }              // temp 释放:buf 回收,O(1)
}

void stack() {
  local Point p = new Point(1,2); // 栈上分配
}
  • 全局 arena

    默认分配

    任何 arena 块之外的 new 都从全局 arena 分配 — 可以安全返回、存储、传给 C。进程退出时由操作系统回收。

  • arena 块

    带作用域且经过检查

    arena temp { … } — 块退出时释放。逃逸是编译错误,静态检查。词法的,不是动态的。

  • local

    栈分配

    local Point p = new Point(...) lowering 为 alloca — 适用于你主动选择的、热的、有界的场景。

  • 没有 destroy()

    Arena 释放即回收

    没有 finalize(),没有 destroy()。文件句柄 close(),密钥 zeroize()DirectArray free() — 其余的都由 arena 释放处理。

后端

AOT 到原生代码 — 没有 VM,没有 JIT,没有要打包的运行时

SuperJ 编译为 LLVM IR 再生成一个自包含的原生二进制。没有字节码,没有类加载,没有 JIT 预热。从第一个请求起就是全速。编译器完全由 SuperJ 自身构建 — 我们用自己的工具链打造工具链。

  • llvm

    优化的机器码

    通过 LLVM 22 直接生成 -O3 原生代码。可选 --enterprise 对 SDK + 用户代码做全程序 LTO。

  • 自托管

    编译器用 SuperJ

    superj 二进制由 SuperJ 产出 — 工具链端到端自举。

  • 目标平台

    macOS 与 Linux

    macOS arm64(kqueue),Linux x86_64 与 aarch64(epoll)。每个目标一个二进制 — 拷过去就能跑。

  • 编译选项

    调节代码生成

    --no-bounds-check--simd=avx2--target-cpu=native--debug。最高性能的配方就一行。

并发模型

设计上单线程 — 用进程横向扩展

线程、锁、synchronizedvolatile 以及 Java 内存模型都消失了。一个事件循环,一个线程,一个因果叙事 — 从结构上就是确定性的。靠 SO_REUSEPORT 跑更多进程来跨核扩展;靠 SEDA sequencer 的全序事件流跨进程协调。

scale.sj
// 一个进程一个核 — 靠多跑几份来扩展:
//   for i in 1 2 3 4; do ./webserver 8080 & done
// 内核在它们之间均衡连接 (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); }  // 一个循环,一个线程
  }
}
  • 无锁

    没有数据竞争

    一个线程意味着没有锁、用户代码里没有原子操作、热路径上没有跨核缓存来回抖动。

  • 确定性

    重放逐位一致

    相同的事件序列 → 相同的状态。bug 可复现。测试不依赖时序。SEDA sequencer 是唯一的排序权威。

  • SEDA

    全序事件

    应用拥有自己的状态;一个 Sequencer 排空命令队列、盖上单调递增的 seq、写入一条事件队列。一致性是序列的属性,不是调度器的。

  • 数学

    三个不可能性结论

    死锁自由不可判定、FLP、CAP — 这个取舍无法回避。SuperJ 把它一次性支付在一个看得见的地方,而不是分散在数千次隐藏的锁获取中。

系统能力

Java 触不到的底层控制力

在 arena 模型之外,SuperJ 还提供了那些你原本得退回 C 才能写出来的原语 — 同时类型系统依然在背后替你把关。

  • local

    栈分配

    local 关键字把 new lowering 为 alloca — 对象在栈上,零堆分配。适用于你主动选定的热的、有界的场景:临时缓冲、哈希累加器、每次调用的上下文。配合 arena 块,一个请求处理器能在热路径上零分配。没有 GC 停顿,没有分配压力,不需要靠逃逸分析去猜。

  • 布局

    固定布局结构体

    无头的值类型,有线格式上确定的布局。view(buf, off) 直接在字节上做轻量视图 — 零拷贝协议代码。

  • 数组

    矩形数组

    int[,] / int[,,] — 连续存储、按步长索引,和锯齿数组 int[][] 是不同的类型。

  • 互操作

    原生 C / Rust

    native 方法直接调用 C ABI — 没有 JNI,没有编组层。链接时直接符号解析。

  • 字符串

    构造上就是 UTF-8

    统一的 string/String 类型,byte[] 后端,长度前缀 + NUL 结尾 — 就是合法的 C 字符串,零拷贝。

加密级数值

宽整数与 SIMD — 一等公民,不是库

现代密码学、大数运算、数值内核需要的原语 Java 根本没有。SuperJ 把它们作为原生类型和关键字提供 — 由 LLVM lowering 成和 C 编译器一样的机器指令,再在上面自动向量化。

crypto.sj
// i128 / i256 / i512 — 有符号的原生原语,不是结构体
i256 x = 6i256;
i256 y = x * x + 1i256;
i256 q = y / 3i256;          // 强度缩减为 limb udiv (#1638)

// secp256k1 标量运算就在这里 — 一次 i256 mod-n
// 就是一条 LLVM sdiv,不是 4-limb 手写循环。

local byte[] h = new byte[32];   // 栈上 — 无堆分配
Hash.sha256(msg, 0, msg.length, h, 0);

// SIMD — 没有新语法,只是带类型的数组
float[4] a = ..., b = ..., c = new float[4];
Simd.addFloat4(a, 0, b, 0, c, 0);   // NEON / AVX2 / SSE2
  • i128 / i256 / i512

    原生宽整数

    一等公民的有符号原语 — 不是库结构体。算术运算 lowering 为原生 LLVM add/mul;除以常量会被强度缩减为 limb udiv + umulh。对现代密码学至关重要:secp256k1、AES-GCM、EIP-712、SHA-3 都原生地操作 256 位值。i256 一般除法 比 C 快 3.4×;i512 除法 快 10.4×;i512 除以常量 快 1483× — clang 还在调 __divti3,SuperJ 直接生成强度缩减后的 limb 序列。

  • SIMD

    一等公民的向量内联函数

    可移植的向量族(Byte16Float4Float8Double2、…)lowering 为原生 SSE2 / AVX2 / NEON IR — 没有新语法,只是带类型的数组。Simd.addFloat4Simd.fmaFloat8Simd.dotFloat8 — 算术、按位、比较、掩码混合、转换、归约、gather/scatter、点积、前缀和。ARM 上 NEON 是基线且始终开启;x86 上可选 --simd=sse2|avx2

  • 自动向量化

    之上还有自动向量化

    即便是标量循环也会被向量化。LLVM -O3 直接对 SuperJ IR 自动向量化:HNSW 的字节 L2 距离循环编译为 usubl.8h/smlal.4s/ldp q NEON(每次迭代 32 字节),无需显式内联函数。一个用 local float[4] 累加器的缓存分块 GEMM 在每一种矩阵尺寸上都比 C 的自动向量化快 1.15-2.57× — 常驻寄存器的累加器同时给了寄存器复用和缓存局部性,而 C 的流式方案只能拿到一个。

  • complex

    复数

    一等公民的 cdouble(128 位)和 cfloat(64 位)原语 — 两个浮点数打包成一个类型。算术(+ - * /)、==/!=,以及完整的 ComplexMath SDK 类(explogsqrtsin/cos/tanabsargconj、…),基于 C99 <complex.h>。虚数字面量:3.0i2.5fi

为什么这很重要。 一门想在原生速度下做密码学和数值内核的语言,需要在类型系统层面拥有这些原语,而不是作为库。Java 的 BigInteger 每次运算都分配、每个值都装箱;Rust 的 u256 是带方法分发的库结构体。SuperJ 的 i256 是一种 LLVM IR 类型 — 后端把它拆成 2×128 位通用寄存器或 AVX-512 zmm 寄存器,优化器像对待任何整数一样对待它。这就是为什么宽整数基准在加法/乘法上与 C 持平、在除法上比 C 快 3-1483×。

GPU & AI

GPU 计算与 LLM 推理 — 一等公民,不是外部调用

sj.gpu 协议栈把 Metal、CUDA 和一个 CPU 参照后端统一在一个 API 之后 — 同一份代码,同样的结果。加载一个 GGUF 模型,prefill,decode:四十行代码,在 Apple Silicon 上比 llama.cpp 更快。

  • gpu

    sj.gpu — Metal / CUDA / CPU

    打开一个 GpuDevice,加载量化模型(Model.load),用 KvCache 跑 prefill + decode。Apple Silicon 上用 Metal,NVIDIA 上用 CUDA,其它平台用 CPU 参照后端 — 同一份代码,逐位一致的结果。见 编写一个 LLM 推理引擎

  • tensor

    面向自定义架构的 Tensor 层

    在高层次 API 之下:一个面向自定义模型架构的 Tensor 层 — 量化 matmul、attention、RoPE,全部作为 GPU kernel。同一套跑赢 llama.cpp 的协议栈。

架构与契约

Claim Layer — 编译器强制的意图

声明每个包可以做什么(capabilities)、可以import 什么(架构)、方法必须保证什么(契约)— 编译器对每一行都照此执行。release 构建中零运行时开销。

  • capabilities

    Capabilities — 每个包最小权限

    Build.sj 中一行:capabilities = { "myapp", "net, fs.read" }。默认拒绝:任何未列出的包都不持有 capabilities。superj capabilities 显示已授予 vs 已使用 — 收紧直到两者一致。见 Claim Layer

  • architecture

    架构规则 — import 边界

    声明哪些包可以 import 哪些包 — 在编译时强制分层。不再有"util 依赖一切"式的腐坏。

  • contracts

    purenoallocrequiresensures

    一词式方法 claims:pure(无副作用)、noalloc(无分配)。用 requires/ensures 写前后置条件 — debug 中检查,从 release 二进制中擦除。

取舍

一份深思熟虑的账本

每一次移除都换来可预测性;每一项保留都是当初让 Java 高效的部分。

✗ 从 Java 移除

  • // 线程、synchronizedvolatile
  • // 追踪式垃圾回收器
  • // 反射与类加载
  • // lambda 与闭包
  • // 自动装箱 / 拆箱
  • // 非静态内部类
  • // 受检异常、模块、finalize()
  • // switch 模式匹配

✓ 从 Java 保留

  • // 类、接口、继承
  • // 带擦除与通配符的泛型
  • // 枚举与匿名类
  • // 异常(全部为非受检)
  • // 可变参数与方法引用 ::
  • // instanceof 模式匹配
  • // 熟悉的控制流与语法
  • // String / string,统一的不可变类型

SDK

开箱即用的系统级 SDK

每个包都在 sj.* 下。用 superj doc --listsuperj doc <class-fqn> 浏览完整 API。

内容
sj.langStringStringBuilderMathIntegerSystem
sj.util集合与哈希、原始类型特化版(IntArrayListInt2IntMapByteSet…)、随机数、base64、位工具
sj.ioFileFileReader/WriterDirectArray、mmap
sj.http增量式 HTTP/1.1 + HTTP/2 服务器、TLS 1.3、cookies、内容类型、路由、静态文件、WebSockets
sj.json手写的增量式 JSON 解析器
sj.seda事件驱动框架(应用 → Sequencer → 事件队列)
sj.cryptoSHA256(ARM NEON)、Secp256k1、EthereumAddress、EIP-712、TLS 引擎
sj.netNioAdapter 事件循环(TCP/UDP/Unix、epoll/kqueue)、UnixGateway
sj.testAsserts、单元测试框架、golden-output 套件

没有自动装箱 — List<int> 是编译错误。原始类型键值用特化集合;引用类型用泛型 ArrayList<E> / HashMap<K,V>。SDK 链接为三种变体 — community(归档)、enterprise(LTO)、vip(源码)— 见下载

生态

可链接的生态就是已编译的生态

SuperJ 是一门 LLVM 语言,所以每个 LLVM 语言生态中已编译的 C-ABI 核心(Rust、C、C++、Zig、Swift)都能通过 native 免费链接:密码学(ring、BoringSSL、libsodium)、压缩(zstd、lz4、brotli)、数值内核(BLAS/LAPACK)、解析器、系统绑定。源码人体工学层(派生宏、async 脱糖)不跨任何语言边界 — 连到 C 也不跨 — 而 SuperJ SDK 覆盖了 Java 人体工学的空缺(集合、JSON、HTTP),所以你很少会想念它。

安全

确定性是更强的属性

SuperJ 没有借用检查器。它杜绝的那一类 bug,对大多数软件来说不值得付出永久的逐行负担。取而代之的是,单线程 + SEDA 给你确定性:每个 bug 都可复现、可修复,没有依赖时序的行为,没有时序攻击面。内存安全是一个通过引入非确定性来获得的否定属性;而确定性从结构上就堵住了更大的漏洞。

阅读内存安全说明 →