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
> 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
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)
wooooow
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
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.
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
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
cc @bozhidar