announcements 2026-11-10

https://github.com/b12n-oss/champaca - a Java runtime inside Jolt Java byte code becomes Chez Scheme the first time a method runs, compiled to native code, so Jolt calls Java libraries in-process with no JVM. • The JDK’s own classes from lib/modules, booting with the module system • Jackson, Guava, Caffeine, Gson, Jsoup, SnakeYAML, SLF4J and commons-lang3 match HotSpot’s output; Spring Boot 4.1.2 and Quarkus 3.40.1 apps start • You can run Spring Boot 4 and Quarkus from Jolt • A jolt fn goes wherever Java wants a single-method interface, and makes real Java classes from jolt fns • A startup cache: warm Hello 0.39 s, first run 6.5 s • Rebuilds OpenLDK (Anthony Green’s runtime for Common Lisp) on jolt; JDK 25, jolt 0.8.24+ • Experimental: the guide’s limitations page lists the gaps Example usage: Come join us in #C0B8G0WB63C

🆒 4
🤯 5

> Spring Boot 4.1.2 and Quarkus 3.40.1 apps start lol, this is hilarious

Yes, it starts and run spring boot with the benchmark toward the end

Wow. It's quite incredible

❤️ 1

What do you get from Chez Scheme in this context, that you don’t get from the JVM? I’d like to understand the benefit and tradeoffs.

Champaca isn’t trying to beat the JVM. It exists so a Jolt program can use Java libraries without running a JVM next to it.

Without it, calling Jackson or Guava from jolt means starting a JVM beside your program and talking to it over a bridge. Champaca runs the byte code inside the Jolt process instead: Each method is compiled to native code through Chez Scheme the first time it’s called, and Java objects live in the same heap as your Jolt code. That buys you: • Plain calls: calling Java is an ordinary function call, with no serialization or IPC, and a Jolt fn works wherever Java wants a callback. • No JVM to install: bb bundle ships the JDK’s class library, minus the VM, with your program. • The real JDK: it runs the JDK’s own classes, so libraries behave as on HotSpot. Eight common libraries, Spring Boot and Quarkus give identical output. The costs: it’s a few times slower than HotSpot’s JIT. Threads take turns, under one global lock. It uses several times the memory. JNI and IPv6 aren’t supported yet. It’s a good fit for a jolt program that needs a Java library or two in-process; for heavy multi-threaded Java work, use HotSpot. It is modelled after the excellent library https://github.com/atgreen/openldk (Common Lisp)

🤯 1
1
🤖 1

I feel this is kinda related to my blog post about cream. Cream sits in between babashka and a full blown JVM when it comes to startup time and memory usage but as soon as you add a few Java libraries and whatnot, you’ll soon end up losing any benefits over a full blown JVM compared to cream. So my question is: do you have a realistic scenario where jolt + your lib uses non-trivial Java libraries and it performs better (startup and/or performance / memory usage)? If not, then this is just a nice 🤯 LLM-experiment, but if there are real benefits, let me know.

Yeah, can it aot the libs easily, I wonder

I already assume AOT

Well, losing the benefits, you’re talking about the cold loading, right?

For me, the main benefit is for legacy code, if you’re building something on Jolt, but really need some existing Java library as a bridge this makes it possible. I kind of think of it like Rosetta on macOS.

it looks like you shouldn’t be using jolt + Champaca if you’re in that situation, if you look at this table: https://gist.github.com/borkdude/83a756abbd491167ea1c4ba6446dfcfb

Yeah, champaca ain’t winning any races yet lol

Prolly a 20x slow down?

@borkdude to be fair, Champaca probably has a lot of optimizing that can be done, so far it’s just proving that it’s possible to do at all

you should not compare just one number, different aspects but nothing really make sense to me here

yeah ok, I’ll take a look next year (if you’re still maintaining it, good luck ;))

I don’t see why we wouldn’t be?

Maintaining an alternative JVM seems like work, but I wish you the best haha

we’re not really maintaining an alternative JVM though, what we’re maintaining is the API layer on top of a different runtime

I’m talking about Champaca. > Java byte code becomes Chez Scheme

right, but Chez Scheme is the runtime, so it’s mechanical translation kind of like wasm

I’m building an alternative JVM right now 😬

Just a mix on TeaVM, so hopefully it’s not a maintenance nightmare

I mean, Oracle and friends bring out critical patch releases with security fixes etc. It’s not just “can we do it” right, but also “are we willing to do the boring work” that comes with maintaining a serious JVM

but if that work is mainly in lib/modules then I guess the churn would be ok-ish

but stuff like security fixes would be part of the VM runtime itself right?

Chez is maintained by Cisco for example, so it’s pretty actively developed.

and with Oracle moving into junk bonds territory, there are questions about what happens with the JVM if they go belly up > MA: Still, Oracle’s credit investors are pricing in more risk. S&P, the big credit rating agency - they downgraded Oracle’s credit in July. Now Oracle is barely above junk status. https://www.npr.org/2026/10/22/nx-s1-6007863/oracles-debt-is-growing-the-tech-giants-investors-are-concerned

The native methods seem to be implemented in , , , , , which probably is the highest point of churn

only looking at the first file https://github.com/b12n-oss/champaca/blob/main/resources/champaca/natives.ss , boy that’s a lot of code…

I mean Jolt itself has a lot of code now too 🙂

but yeah you have to map out all the elements to translate them, so a lot of it is just mechanical mapping that’s necessarily going to be long since java surface is big

but the flip side is that Java is really well specified so you can have robust regression testing

@yogthos This is different no? I feel you're talking about the Jolt shims? But this is a compiler from bytecode to scheme no? Knowing AI, I wouldn't be surprised if it's hiding a few interpreters and stack machines in there somewhere to get it working 😛 I'm not sure I'd use this apart for just getting things running on Jolt for fun, say I wanted to try and have Minecraft running on Jolt for example. In that sense, I do see it a bit like TeaVM, which is cool but nobody really uses I feel. Because at that point you're much better just actually porting your app instead of running it through some emulation layer. P.S.: Super cool though and crazy it even works

Yeah, I’m kicking the tires on the champaca stuff. IIUC, you actually have to have the JDK available at dev time

But you can ship without the jdk

in the app or lib

So it’s more-so about allowing a JVMish deployment situation, without the jvm

Why do you need the JDK? You mean just to get compiled bytecode?

IDK, I think it pulls it in to gen the classes

@didibus yeah you need the JDK to extract the code first, but I think it could map directly to Jolt shims going forward

I can’t really see any fundamental reason why that wouldn’t work here

Precompile certain classes for certain legs?

behind the shim surface?

what I’m thinking could happen is you make a fasl file at build time with the translated code that terminates at Jolt’s Java API layer

the original LDK project this is based off targets CL which doesn’t have a native Java layer in it, so there is a lot of work being done that’s not strictly needed on Jolt

It would work, but it's not what I expect a shim to be. I expect a shim to be a proper Jolt implementation that just runs through a compatibility interface. Whereas this is a transpiler that's kind of pulling in everything under the hood and not really re-implementing on Jolt but kind of transitively transpiling and bringing in the whole shabang.

so we could both flesh out the Java compatibility layer more in Jolt itself and then strip Champaca down to just being a code translator

This lets you run some java libs with your clj app

yeah basically, and if we can get performance to be decent, then it would provide a really strong bridge from the JVM

So, you’re saying, use some fasl file to aot your java libs and then fall back to the shim layer? Wouldn’t the LDK/champaca be the fallback? Since it’s more comprehensive?

oh I mean translate Java code to a fasl file that sits on top of the shim layer

> on top of the shim layer I don’t get that part

so anything that’s already in Jolt as shims would terminate there, but anything that’s not in Jolt would get translated and built

like say the code fall the File class in Java, that’s in Jolt, so we can just point to it natively

Seems like the shims would be passive in that case. A pure subset

but if the code calls some class that’s not implemented, just extract it from the JDK and the libraries

the shims still point back to chez… hmmm. Gotta dilineate that by the memory model

The performance/memory/bundle-size is a big IF. But it's all it comes down to in the end, and I guess also the if dev experience remains lean and friendly. The shims to me seem like they'd always be more performant, use less memory, have smaller bundle sizes, pull in less initial code to build (so faster build times), and have a better dev experience. So seems preferred to me. But if this could get very competitive at those, then I guess.

well technically there’s an extra layer Jolt has Java shims that sit on top of portable Scheme layer, and then there’s the host layer under that which is the specific Scheme runtime like Chez or Gambit, or whatever you have

> The shims to me seem like they’d always be more performant, Well, if you go all the way with that, you’re talking about shimming out the whole jdk

☝️ 1

@didibus yeah shims are the more performant option, but we’re not going to implement the whole JDK surface on top of Jolt, plus say you use a Java library that’s not part of the JDK, then you’d have to effectively reimplement it to use shims

I just feel, intuitively, like this wouldn't be able to get competitive enough. And in the day and age of AI, it's not a blocker, I can port Guava to Jolt and likely end up with a more performant, leaner, lower memory, and so on result. Pre-AI I couldn't easily port (or shim) what I'm missing and this would have been a fallback with compromises I might be willing to make.

we’ll have to see, I mean this could also work as a reverse engineering tool for LLMs to use

If you split half the java calls to chez and half the calls to LDK, you’ll have to marry up their memory models underneath somehow

if it can unpack the Java bytecode from jars, then the LLM can rewrite it after easily too

I guess I see that it's cool, but I don't see myself using it 😅, except for fun.

it’s very much an experiment right now 🙂

I think it’s about having the freedom to use the right tool for the job for the situation

💯 1

And if we're talking about fun.. Why stop at Java? Can we do the same with Python compiled files? With .NET IL ?

Not about displacing the JVM for what it’s best at

in theory I don’t see why not

the more I think about it, it might actually be interesting to see if this approach can work as a guardrail for the LLM to do a port faithfully

if it can be used to extract the code and then provide some validation mechanism to make sure that the native rewrite the LLM does conforms to the original, that’d be incredibly useful

@john In terms of ecosystem maturity and development, as Steve Jobs says, focus is what you decide not to do. I think the concern is that instead of effort going into shims or porting missing libraries/framework, this is used instead. Will Jolt apps more and more just be emulated Java apps? Though I can see the reverse argument as well, this being a jumping bridge and it pushes people to adopt Jolt faster as things immediately exist, and later invest in ports or new Jolt-native libs/frameworks.

that’s kind of my thinking, if this provides a bridge right now, I can actually focus on jolt itself instead of building out the ecosystem to match the jvm

I kind of see this as the Rosetta approach Apple used when moving to ARM

and if you’re building a fresh app, there’s little reason to reach for this because it’s easier to just do FFI to native libraries anyways

the main use case here is you have some existing app that has tight Java coupling that you want to migrate

So, we could make clinj.clj cover the whole JDK api and then port that to all the clj*s. Then all the clj*s will have the whole jdk shim layer, mapped to their runtime. Then we do a shim layer for every runtime. Clinclr, clinply, clincpp (through jank) etc

😀 1

I think that's what GraalVM polyglot does no?

Then you have a matrix of all runtimes to all runtimes, through cljc

Probably at some level

Not sure if it uses shims

Shims is a very fast mapping method, rather than emulation method

Then, when you have a runtime mapping between all the runtimes, and you’re running them together, the #? becomes a runtime directive at the repl for sending certain forms to certain runtimes at run time.

At the same time

Hum, seems GraalVM is more like you implement an interpreter for another language in Java, and then, it automatically can be JITed

shims is a compile time solution

> This is different no? I feel you’re talking about the Jolt shims? But this is a compiler from bytecode to scheme no? No, look at the file I linked. The native method definitions are huge amount of Scheme code.

1200 lines is hardly huge in the context of shimming out the JVM API though, look at the size of the JDK source code itself for comparison

you mean the line-count of this whole directory right? 1200 was just one file. https://github.com/b12n-oss/champaca/tree/main/resources but yeah maybe it’s all kinda ok

right, overall amount of code is not in any way comparable to the size of the JDK itself

and most of that code is just translating stable and mature APIs too, so it’s not like it’s going to be changing a lot either, or there’s some complex logic happening there

It is an experiment, I think we can get to improve Jolt in the process and maybe perhaps we can make it part of Jolt later once we know more.

also, would you say champaca scheme is more complex than SCI analyzer? https://github.com/babashka/sci/blob/master/src/sci/impl/analyzer.cljc

Hey, I’d like to share something I’ve been using for a while in my projects and now I open sourced. taia.ds 0.2.0 — Datastar + XState-style state machines + Clojure: an opinionated, component-based library for server-side UI. A component is a pure render fn (ctx → hiccup) plus a hierarchical state machine (XState-like: nested states, guards, actions, invoke - for side effects). Events arrive as HTTP POSTs (`/ds/nds/<component>/<id>/<event>`), the machine transitions, the component re-renders and Datastar patches the DOM over SSE. State round-trips through signals, so there is no server-side session; connected components get server push (`send-ui!`). If you know re-frame: same shape, but the event loop runs on the server and the view is hypermedia. Extracted from a production app, now a Polylith library on Clojars: io.github.danbunea/taia.ds {:mvn/version “0.2.0”} • GitHub: https://github.com/DanBunea/taia.ds (README has re-frame and XState comparisons, six runnable examples with state diagrams) • Docs: https://cljdoc.org/d/io.github.danbunea/taia.ds/0.2.0 • Reference project: https://github.com/DanBunea/TodoMVC-AI-Agent (TodoMVC with an AI agent on the same list) Feedback welcome, especially from people using Datastar or statecharts in Clojure.

👀 6
🚀 3
🎉 7

https://github.com/nextjournal/markdown: A cross-platform Clojure/Script parser for Markdown 0.7.232 • Add option :strikethrough-require-two-tildes true to parse x as strikethrough, but not x #75 • Parse ~x~ as strikethrough and ~~~x~~~ as text in ClojureScript. Set :strikethrough-require-two-tildes true to keep ~x~ as text #75 • Parse $5 and $10 as text and $$x$$ inside a paragraph as one inline formula on the JVM #74

🎉 7

https://github.com/nextjournal/clojure-mode 0.3.5 • Bump squint-cljs to 0.15.212 • Depend on @codemirror/lang-markdown ^6.0.0 instead of exactly 6.0.0 0.3.4 • Make Option+S run unwrap on macOS with @codemirror/view 6.38.1 or later (https://github.com/nextjournal/clojure-mode/pull/62) • Make Backspace delete an escape sequence in a string as a whole, instead of leaving a backslash that escapes the closing quote (https://github.com/bbatsov) • Fix https://github.com/nextjournal/clojure-mode/issues/63: typing " before the closing quote of a string moves past it • Handle a bracket typed after the \\ character literal as code (https://github.com/nextjournal/clojure-mode/pull/66) • Fix wrapping a selection in brackets with the squint build (https://github.com/nextjournal/clojure-mode/pull/67) • Insert a closing bracket typed in a line comment, instead of dropping it and jumping to the next closing bracket after the comment (https://github.com/bbatsov) • Bump squint-cljs to 0.11.188

1
❤️ 1
5