Warning
Experimental. Champaca runs real Java programs and libraries with the same output as HotSpot, but it isn't a complete JVM. A program can still reach a JDK native that hasn't been written yet (an UnsatisfiedLinkError, named on stderr with CHAMPACA_BT=1), JNI libraries aren't there, and a warm start takes a few times HotSpot's time and memory. The limitations page lists the gaps, and debugging shows how to read one.
Champaca is a Java runtime inside jolt. It rebuilds OpenLDK, Anthony Green's Java runtime for Common Lisp, on jolt. A translator written in jolt's Clojure turns each method's bytecode into Chez Scheme source the first time the method is called, and jolt.scheme/eval-string compiles that to native code. Java objects are Chez records in jolt's own heap, so jolt code calls a Java library as a plain procedure call, with no second runtime in the process.
The classes are the JDK's own, read from $JAVA_HOME/lib/modules, and the JDK boots as it does on a JVM, module system included. So System.out.println goes through PrintStream and the UTF-8 encoder before it reaches a FileOutputStream.writeBytes that champaca implements over libc.
If you know babashka, champaca goes the other way. Babashka is a Clojure interpreter compiled ahead of time with a fixed set of Java classes. Champaca compiles jolt's Clojure natively and loads any Java class file at run time, though its first start is slower. compared-to-babashka puts the two side by side.
(require '[champaca.api :as ldk])
(ldk/init!)
(ldk/invoke-static "java.lang.Math" "max" 3 7.5) ;=> 7.5
(let [xs (ldk/construct "java.util.ArrayList")]
(doseq [w ["pear" "fig" "apple" "kiwi"]] (ldk/invoke xs "add" w))
(ldk/invoke xs "sort" (fn [a b] (compare (count a) (count b)))) ; a jolt fn as a Comparator
(ldk/invoke xs "remove" 0) ;=> "fig" (remove(int))
(ldk/invoke xs "get" 0) ;=> "pear"
(ldk/to-string xs)) ;=> "[pear, kiwi, apple]"
(ldk/->clj (ldk/invoke "a,b,c" "split" ",")) ;=> ["a" "b" "c"]
Methods are found by name, and the overload is picked from the arguments the way javac picks one. A jolt fn goes wherever Java wants a single-method interface. Jolt collections become Java ones on the way in, and results come back as jolt values where they can. calling-java and data-conversion have the details, proxies and Java classes defined from jolt among them.
jolt libs checks each one: commons-lang3, commons-lang 2.4, commons-io, commons-compress, Commons Math, gson, jsoup, Jackson and its XML module, Caffeine, Guava, Guice, Joda-Time, Kryo, Netty, SLF4J, Log4j 2, SnakeYAML, picocli, the H2 database, Lucene, Bouncy Castle and Byte Buddy (jars-and-modules).jolt libs checks them in CI (jvm-languages).java: -cp, -jar, -D options, -p and -m for modules, source files, and the JDK's own rules for finding main (running-java-programs).java.lang.foreign, each checked against HotSpot (compatibility).Hello takes 0.39 s from exec to exit on an M1 Pro, where the first run took 4.3 s (performance).jolt bundle makes a directory that runs a program on a machine with no JDK (app-bundles).You need jolt 0.8.24 or later and JDK 25, with JAVA_HOME set.
jolt jolt # build the jolt commit deps.edn pins, once
jolt test # every test program against the JVM, plus the examples
jolt -M -m champaca.main target/classes Hello # run a class jolt test compiled
getting-started covers depending on champaca from your own project and using it from an editor. development lists every task and switch.
java-like launcher, frameworks.CHAMPACA_* switches.A champaca, Magnolia champaca or จำปา in Thai, is a tall tree from South and Southeast Asia, a relative of the magnolias. Its flowers have narrow tepals that run from gold to saffron orange, and their scent is strong enough that the oil goes into perfume.

Michelia champaca (now Magnolia champaca), plate 191 of Francisco Manuel Blanco's Flora de Filipinas, Gran edición, Atlas I (about 1880 to 1883). Public domain, via Wikimedia Commons. The logo in docs/images/logo.svg was drawn for this project.
GPLv3 or later with the Classpath Exception, inherited from OpenLDK. See COPYING and COPYING.CLASSPATH-EXCEPTION. Each source file, task file and script starts with the SPDX line GPL-3.0-or-later WITH Classpath-exception-2.0 and a copyright line, crediting OpenLDK where it derives from OpenLDK, as OpenLDK's own files do. Four pieces that once followed GPL-version-2-only OpenJDK code (src/champaca/npe.clj, class-cast-message in runtime.ss, the class name checks in natives.ss, encode-path in classpath.clj) were written again from HotSpot's observed behavior. jolt bundle ships jolt's EPL-2.0 binaries beside this GPL code, a pairing that isn't settled yet (app-bundles). The Java test programs carry no header, since their recorded output has line numbers in it. The test programs in test/aaa are OpenLDK's own, under the same license (test/aaa/README.md).