rustc_codegen_jvm: compiling Rust to Java bytecode with real interop
Compile Rust to Java bytecode and runnable JARs.
At a glance
- What is it?
- rustc_codegen_jvm is a Rust compiler backend that emits JVM bytecode, so a crate becomes a runnable jar for Java 8 and newer, and the interop goes through ordinary classes and interfaces rather than native handles, which is where the interesting part sits.
- Who is it for?
- rustc_codegen_jvm fits a team that wants to run Rust on a JVM without writing JNI glue, because a Rust enum becomes a JVM interface with variant classes and a Rust trait can be implemented on a Java or Kotlin class, so the interop is a language-level relationship rather than a bridge over opaque handles.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A compiler backend, not a transpiler
rustc_codegen_jvm is a custom Rust compiler backend that compiles Rust directly to Java Virtual Machine bytecode, so a crate becomes a runnable .jar compatible with Java 8 and newer. Calling it a backend matters, because that is where it sits in the toolchain: it takes the same Rust front end and the same MIR that rustc itself works on, and changes what comes out the other end. The alternative, and the traditional approach, is to compile Rust to native code and call into the JVM through a foreign function interface, which is exactly the path this project is trying to get away from. The claimed benefit is interop that is deeper and more ergonomic than FFI or bridge solutions, and the specific claim is that Rust enums, structs, traits and function pointers lower to ordinary JVM classes and interfaces rather than opaque native handles.
Interop that crosses the language boundary in both directions
The interop claims are specific enough to be checked against the test suite, and that is where the project earns its credibility. You can implement a Rust trait on a JVM class and pass it to Rust as a &dyn Trait, pass Java or Kotlin lambdas to Rust Fn closures, and await Rust async functions from Kotlin suspend code while retaining Kotlin's coroutine dispatcher. Rust enums can be constructed, inspected and compared as JVM interfaces and variant classes, including transparent enum subtypes, and you can call JVM constructors and access instance or static fields from Rust without JNI glue. The worked example in the overview shows one Rust API exposing an enum and accepting both a JVM implementation of a Rust trait and a standard JVM lambda, with the result crossing the Rust and Kotlin async bridge. The payload conventions are stated too: single tuple payloads use value, multi-field tuples use _0, _1 and so on, and struct-like variants retain their field names, so Kotlin can destructure any payload variant.
A virtual MMU makes raw pointers work on the JVM
The technique that makes the rest possible is a translation layer the project calls a virtual MMU, implemented in runtime/src/Pointer.java. Because pointers are virtualised rather than native, the backend can support raw pointers with complex pointer arithmetic, transmute, and unions, and it can support key parts of the Rust standard library including networking, async and await, threading, unwinding and allocation, as well as file system operations and standard input and output. Each of those claims links to a test in the tests/binary/ tree, which is the right way for a compiler backend to make them: a Rust source file that exercises the feature, compiled to bytecode and run. The tests/binary/ directory name, and the separate tests/integration/ and tests/kotlin/ trees for cross-language cases, describe how the project is organised around proving the boundary works.
The upstream test suites are the measure of how complete it is
The strongest evidence in the overview is a number, and it is a specific one. Every selected official Rust coretests and alloctests test passes in CI in both debug and release mode, and CI currently verifies 2,812 of 2,817 coretests and 1,474 of 1,477 alloctests, which the project puts at roughly 99.8 percent of the upstream test suites. Running the official Rust test suites against your own backend is the right bar, since it means the claim is not about a hand-picked demo but about the language and standard library as upstream defines them. The repository carries the machinery for this at the top level, with Coretests.py, Alloctests.py, Tester.py, build.py and Metrics.py, plus a stdlib_overlay.py, a stdlib_test_harness.py and a test_harness.py, which suggests the tests are adapted rather than run raw.
Getting a hello world onto the JVM
The quickstart is short, and the first step is installing the cargo-jvm driver from the repository itself. If you are on Windows, the project asks you to use PowerShell so that $PWD will work.
git clone https://github.com/IntegralPilot/rustc_codegen_jvm
cd rustc_codegen_jvm
cargo install --path cargo-jvm
cargo jvm setup "$PWD"The setup command installs and selects the backend's pinned Rust nightly automatically, and the project makes a point of saying that your default toolchain can remain stable. That separation is what makes the backend usable at all, since the badge at the top of the overview says the Rust requirement is a pinned nightly. Then you create an ordinary Cargo project.
cargo new hello_world --bin
cd hello_worldAnd you build and run it on the JVM.
cargo jvm runYou should see Hello, world! printed to the console, which is the moment the whole idea becomes concrete: the same Cargo workflow, producing a jar instead of a native binary.
What it does not do yet, in the project's own words
The overview does not oversell the state of the work. A note says the project is in an active mid-stage of development, that it supports the vast majority of the Rust language, that edge-case bugs are continually being ironed out, and that the ultimate goal is potential upstreaming into main rustc. That last point is worth understanding for what it implies about stability. A backend that is a candidate for upstreaming is a backend whose interfaces are still moving, and the project is candid that the remaining edge cases are exactly the sort of thing that bites in production. The repository carries a Current Limitations section in its table of contents, and that is the part to read before you commit a service to it.
The reach beyond current native targets, and the OpenJDK work
Two claims go beyond simply replacing a compiler backend. The first is that the backend enables modern Rust code to run on older platforms outside the reach of current native targets, which follows from targeting Java 8 and newer rather than a specific operating system and processor combination. The second is that the project has integrated upstream changes into OpenJDK's C2 JIT compiler, which the project says can make the JVM faster for everyone, including about 1.85 times faster 128-bit multiplication on x86, and that is a link to a pull request in the OpenJDK repository. The project was written in Rust and is licensed MIT or Apache-2.0, with both licence files present at the repository root. The last push was on 2026-10-17 and there are no GitHub releases, so the repository is the only distribution channel.
How the repository is laid out
The directory names tell you how the pieces fit together. There is compiler-core/ for the backend itself, referenced from Cargo.toml as the jvm-compiler-core crate with a serde feature, and the root package depends on ristretto_classfile at version 0.31.0 for emitting class files, patched to a fork at a pinned revision. The Cargo.toml is edition 2024, marks the crate type as dylib because it is a compiler backend rather than an application, and sets rustc_private=true in the rust-analyzer metadata, which is how a backend is allowed to use rustc's internal APIs. Alongside that sit jvm/ for the runtime support, runtime/ for the Java side, java-linker/ for the linking step, std/ for standard library support, cargo-jvm/ for the Cargo driver, src/ for the backend crates, and the test_harness and test trees. The .templates in the root, config.toml.template and jvm-unknown-jvm.json.template, are the shape a custom target needs.
Editorial conclusion
rustc_codegen_jvm fits a team that wants to run Rust on a JVM without writing JNI glue, because a Rust enum becomes a JVM interface with variant classes and a Rust trait can be implemented on a Java or Kotlin class, so the interop is a language-level relationship rather than a bridge over opaque handles. It does not fit a production deployment today, because the project describes itself as being in an active mid-stage of development with edge-case bugs continually being ironed out, and it publishes no GitHub releases at all, so there is no version to pin. Before you build on it, run the upstream test suites it names yourself, coretests and alloctests, since the project says it verifies 2,812 of 2,817 coretests and 1,474 of 1,477 alloctests in CI, and read the current limitations section, because the remaining gaps are exactly where your code is most likely to land.
Frequently asked questions
What is rustc_codegen_jvm?
It is a custom Rust compiler backend that compiles Rust directly to JVM bytecode, producing a runnable .jar compatible with Java 8 and newer. Rust enums, structs, traits and function pointers lower to ordinary JVM classes and interfaces rather than opaque native handles.
How do I build and run a Rust project on the JVM with this backend?
Clone the repository, run cargo install --path cargo-jvm and cargo jvm setup "$PWD" to install the driver and the pinned nightly, then create a project with cargo new and run it with cargo jvm run. On Windows, use PowerShell so that $PWD will work.
How complete is the Rust standard library support?
The project says it supports key parts of the standard library including networking, async and await, threading, unwinding, allocation, file system operations and standard input and output, through a virtual MMU translation layer. Every selected upstream coretests and alloctests passes in CI in debug and release mode, with CI verifying 2,812 of 2,817 coretests and 1,474 of 1,477 alloctests.
Can Rust and Kotlin code interoperate directly?
Yes. You can implement a Rust trait on a JVM class and pass it as a &dyn Trait, pass Java or Kotlin lambdas to Rust Fn closures, and await Rust async functions from Kotlin suspend code while keeping Kotlin's coroutine dispatcher. JVM constructors and instance or static fields can be called from Rust without JNI glue.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/integralpilot-rustc-codegen-jvm)Was this useful?