Skip to content

tegmentum/fiji

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2,993 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fiji

Fiji is a Java runtime for the WebAssembly component ecosystem.

Releases · Documentation · Changelog · Release manifest


0.4.x establishes a stable runtime and component contract. 0.5.x aims to make Java a first-class component language rather than merely a guest running inside components.

What is Fiji?

Fiji is a Java Virtual Machine packaged as a WebAssembly component. It exposes a public WIT contract (fiji:jvm/jvm@0.1.0) that lets a host load .class bytes, invoke Java methods, exchange typed values with Java objects, and tear the VM down — all without linking against JNI or shipping a native libjvm.

A real Java runtime executes the bytecode.

Works with your existing toolchain

Take the JARs and .class files you already have and run them on Fiji. Fiji is an additional deployment target for Java code, not a replacement ecosystem.

  • Standard javac output runs unchanged. Compile with any JDK 21+ javac you already have.
  • No Fiji compiler. No javac wrapper, no Fiji-aware build step.
  • No annotations. No @FijiExport, no @FijiEntryPoint, none of that. Your source is unchanged.
  • No bytecode rewriting. No agent, no instrumentation pass, no transformation of class files.
  • No build plugin. No Maven plugin, no Gradle plugin. Use the plugins you already use.

If it builds on a normal JVM today and respects the boundaries in dist/CONSTRAINTS.md, it runs on Fiji tomorrow. Your existing Maven, Gradle, IDE, and CI pipelines work as-is.

One artifact. Every runtime.

Compile once with standard Java tooling. Deploy the same artifact across browser, server, edge, and embedded environments. No per-target build, no runtime-specific variant, no second toolchain.

Target What runs
Browser Same .wasm, transpiled for the browser via jco
Server Same .wasm, run under standalone Wasmtime or any native component-model runtime
Edge Same .wasm, on any Wasm-component-capable edge runtime
Embedded Same .wasm, linked in-process via the Wasmtime crate (or any component-model implementation)

The same Java bytecode, the same component artifact, the same public WIT contract — across all four host categories. Tutorial 5 in the release tarball (05-same-artifact-several-runtimes/) demonstrates this end-to-end.

Why Fiji?

Most existing options for running Java in non-Java environments involve a tradeoff that loses something fundamental about Java:

  • Compiling Java to a native binary (e.g. AOT image builds) loses the portability story — you get one binary per platform rather than one artifact that runs anywhere.
  • Transpiling Java to Wasm directly loses semantic fidelity — reflection, dynamic class loading, and full classpath search rarely survive the translation cleanly.
  • Embedding a native JVM via JNI loses the deployment story — the host must link against libjvm and ship platform-specific binaries.

Fiji's bet is different: keep a real JVM, package it as a WebAssembly component, and let the host talk to it through a typed WIT contract. The result is one artifact that runs in any component-capable host (wasmtime, jco, browsers via jco), preserves the semantics standard Java tooling already produces, and exchanges typed values with non-Java components without any JNI surface.

Pick Fiji when you want:

  • Full Java semantics (real bytecode, real reflection) running in a component-capable host.
  • A single artifact rather than per-platform native binaries.
  • Typed cross-language interop with Rust, Python, or any other component-capable language — through a WIT contract, not JNI.

What works today

  • Run Java workloads (any .class files compiled by a standard javac) inside a Wasm component runtime.
  • Exchange typed values (primitives, strings, arrays, object references) between Java and the host via the public WIT.
  • Compose Fiji with other Wasm components — give Java code access to non-Java capabilities through component-model interfaces rather than JNI.

The release ships an end-to-end verification path that any consumer can run against their installation.

Install

The fastest way to install Fiji and its required Wasmtime runtime:

curl -fsSL https://fiji.dev/install.sh | sh

The installer detects whether a supported Wasmtime is already on your PATH and only installs one if needed. If you'd rather manage WebAssembly runtimes yourself, install Wasmtime (wasmtime.dev) directly — Fiji works with any installation method that puts wasmtime on PATH at a supported version.

For users who want a dedicated WebAssembly runtime manager, we recommend wvm. Fiji's installer uses it when needed, but Fiji itself does not depend on it at runtime: fiji doctor only checks for wasmtime.

After installation:

fiji --version       # print release version
fiji doctor          # diagnose whether the host has a supported Wasmtime
fiji verify-release  # run the release verification floors
fiji manifest        # emit MANIFEST.json
fiji wit             # emit the public WIT

Hello, Fiji

The smallest end-to-end demonstration — a standard javac-produced .class running inside a Wasm component:

// HelloFiji.java
public class HelloFiji {
    public static void main(String[] args) {
        System.out.println("Hello from Fiji.");
    }
}
javac --release 21 HelloFiji.java
wasmtime run --dir=. fiji-runtime-hotspot.component.wasm HelloFiji
# → Hello from Fiji.

No Fiji-aware API. No annotations. Standard javac output, running inside a WebAssembly component, producing the output you'd expect.

The release tarball ships two ready-to-run tutorials in tutorials/:

  • 01-hello-fiji — the example above, fully wired.
  • 05-same-artifact-several-runtimes — the same workload + same component artifact under multiple host categories (standalone wasmtime, Node via jco, with pointers to browser and embedded-library hosts).

Publish a Java library as a Wasm component

Beyond running a Java application inside a component, Fiji can serve as the runtime behind a component package — a Java implementation exported through a non-Fiji WIT interface that consumers bind against without any awareness of Java or Fiji.

That is a different product surface from the runtime: Java becomes another implementation language for producing component-model packages, alongside Rust, C, Go, and the rest of the component-model ecosystem.

The first end-to-end demonstration lives in-repo:

Walk-through: Tutorial 3 — Publish a Java library as a Wasm component.

The consumer-visible contract is clean today. The remaining frontier is internalizing the JDK class image so the consumer needs zero Fiji-side execution prerequisites; until that lands the consumer preopens the image at /jdk via an env var. The contract surface is unaffected.

Public versus internal

  • Publiccomponents/wit/fiji-jvm.wit. This is the contract. Consumers bind against the package fiji:jvm@0.1.0 and treat everything documented there as stable for the release line.
  • Internal — every other component, every other WIT file, all composition pins, and the runtime's internal layout. Treat as implementation detail; subject to change between releases.

Known limitations and supported surfaces

Every release ships both boundaries of what runs on Fiji:

  • Negative boundarydist/CONSTRAINTS.md: what does NOT fit. Short form: no AWT/Swing, no unrestricted native library loading, no unrestricted process spawning. Workloads that depend on those surfaces fail clearly at the boundary rather than silently degrading.
  • Positive boundarydoctrine/envelope-0.4.md: what DOES fit, organized by category (execution hosts, Java features, networking, file I/O, encryption, composition, validated applications). Each row carries a ✓ / △ / ✗ classification with empirical evidence pointers. Use it to self-classify a workload before adopting Fiji.

Where is Fiji going?

0.4.x is the runtime-and-contract stabilization line. The WIT contract, the artifact set, and the consumer surface are all stable. New 0.4.x releases are bug fixes and forward-compatible extensions; the contract itself is frozen against fiji:jvm@0.1.0.

0.5.x will make Java a first-class component language. In 0.4.x Fiji is the runtime that runs a Java program inside a component; in 0.5.x Java libraries themselves become consumable WebAssembly components. The intent is that a Rust or Python developer should be able to consume a Java component without needing to know anything about Fiji internals — a Java library appears as a typed component on equal footing with one written in any other language.

The first end-to-end proof of this lives in 0.4.x already (see the section above on publishing a Java library as a Wasm component); the categorical move at the contract surface is demonstrated. The remaining 0.5.x work is making the resulting artifact self-contained — bundling the JDK class image into the component so no consumer-side preopen is required.

Beyond 0.5.x, the trajectory continues into workflow bridges (treating Java's traditional library ecosystem as bridges into the component world rather than dead-ends outside it) and operational hardening. Fiji is a platform for Java in the component world, not an experiment.

Documentation

Full documentation — tutorials, API reference, release notes, contributor doctrine — lives at tegmentum.github.io/fiji.

In-repo references:


Contributing

The sections below are for contributors working in this source repository. Consumers running the Fiji release tarball generally need only the sections above.

Repository layout

Top-level path What lives here
assets/ Brand assets (logo). Copied into the release tarball by the factory.
build/ Wasm component build outputs (substrate, composed components).
crates/ Rust crates — facade, runtime smoke harnesses, host bindings.
dist/ Reference inputs for the release factory (e.g. CONSTRAINTS.md).
docs/ Contributor design notes (legacy). Not shipped in the release tarball.
doctrine/ Contributor doctrine — closure specs, design specs, evidence. Not shipped in the release tarball.
website/ Docusaurus source for the public documentation site (deployed to GitHub Pages).
experiments/ OpenJ9 and other research substrates. Out of the Fiji release train.
release/ Assembled release artifacts (fiji-<version>/ directories + tarballs).
scripts/build/ Release factory — package-release.sh is the entry point.
smokes/ Build-time + release-time smokes that gate the release floors.
tutorials/ Tutorial sources copied into release tarballs.
upstream/ Vendored upstream sources (OpenJDK, etc.).

Cutting a release

./scripts/build/package-release.sh <VERSION>

The factory enforces a deny-default consumer-vocabulary gate (scripts/build/consumer-vocab-allowlist.txt is the audited exception list), a provenance commit-timing cross-check, and floor verification against manifests/MANIFEST.json. The architectural invariant the factory operates under is documented at doctrine/specs/release-artifact-is-not-a-repository-snapshot.md.

Other contributor surfaces

  • SUPPORT_SURFACE.md — historical legacy — describes a frozen fijivm-cli interpreter+JIT path from earlier in the project; superseded by the post-#622 component pipeline. Kept for archive reference only.

License

Fiji is licensed under the GNU General Public License, version 2, with the Classpath Exception (GPL-2.0-only WITH Classpath-exception-2.0) to match the OpenJDK upstream it embeds and patches. The full text is in LICENSE at the repository root.

Third-party components

Vendored upstream sources retain their original licenses:

Component Path License
OpenJDK upstream/jdk/ GPLv2 with Classpath Exception (upstream/jdk/LICENSE, upstream/ADDITIONAL_LICENSE_INFO, upstream/ASSEMBLY_EXCEPTION)
Eclipse OpenJ9 experiments/openj9-wasm/openj9/ EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0 (experiments/openj9-wasm/openj9/LICENSE)
Eclipse OMR experiments/openj9-wasm/omr/ EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0 (experiments/openj9-wasm/omr/LICENSE)

Additional third-party notices (Unicode, MurmurHash3, libffi, zlib, CuTest, Google Test, pugixml) are documented in the respective NOTICES.md / NOTICE.md files under each vendored tree.

About

A Java runtime for the WebAssembly component ecosystem — standard javac output runs inside a Wasm component, with typed cross-language interop through WIT.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors