Chicory Documentation

repository·main·Indexed 22 days ago

https://github.com/dylibso/chicory

A pure-Java WebAssembly runtime designed to run Wasm modules on the JVM without native dependencies or JNI. Chicory prioritizes safety, simplicity, and portability over maximum execution speed, providing full support for the core WebAssembly specification and WASI (wasip1). The project includes tools for differential fuzz testing using wasm-smith, JMH performance benchmarks, and support for running instrumentation tests on Android (API 33+).

Tokens
28.5K
Snippets
77
Records
121
Agent score
77%

What's inside Chicory

  1. Overview of WASI support in Chicory

    main
    Chicory provides support for instantiating and running WASI (WebAssembly System Interface) modules. It implements the wasip1 specification (WASI version 0.1), which provides a virtual system interface with POSIX-like syscalls. This allows WebAssembly modules to interact with system resources in a standardized way.
  2. What is Chicory?

    main

    Chicory is a JVM-native WebAssembly (Wasm) runtime. Unlike runtimes written in C, C++, or Rust (such as v8, wasmtime, or wasmer), Chicory is written purely in Java. This allows you to run WebAssembly programs with zero native dependencies or JNI, making it highly portable across any environment that supports a JVM.

    Key Benefits

    • Zero Native Dependencies: You can distribute your Java application (as a JAR or WAR) without needing to bundle architecture-specific native binaries.
    • JVM Safety and Observability: Because it is a pure JVM runtime, you do not need to use FFI to execute modules. This keeps your security guarantees, memory safety, and debugging tools within the JVM ecosystem.
  3. Chicory 1.0.0-M2 Features: Tail-Call Optimization and SIMD

    main

    Chicory 1.0.0-M2 introduces several technical improvements to WebAssembly compatibility:

    • Tail-Call Optimization: The interpreter now implements the Tail-Call Optimization Proposal.
    • SIMD Support: Implementation of missing SIMD opcodes has begun using a layered approach, maintaining compatibility with Java 11 where necessary and utilizing the upcoming Vector API for encoding.
  4. Chicory performance and roadmap

    main

    Chicory is currently evolving with several key focus areas for future development:

    • Integrations: Expanding availability in major frameworks and products.
    • Spec Compliance: Aiming for full WebAssembly standard compliance, including Exception Handling, Garbage Collection (GC), and SIMD support.
    • Experimental Modules: Refining -experimental modules by fixing bugs, removing limitations, and stabilizing APIs.
    • Performance: Increasing execution speed through ongoing optimization efforts.
  5. How Lumis4J achieves high performance and portability

    main

    Lumis4J leverages several technologies to provide a robust developer experience:

    • Chicory: Compiles WebAssembly (Wasm) modules into Java bytecode, allowing the library to run on the JVM and Android without native binaries or JNI.
    • WASI: Lumis is written in Rust with WASI support, making it compatible with the sandboxed Wasm runtime.
    • Wizer: A Wasm pre-initializer used to preload grammars and themes at build time. This solves the 'cold start' problem where loading a language for the first time could otherwise take seconds.
    • Sandboxing: The Wasm runtime uses a heap that is fully separated from the JVM heap. Memory bugs in the underlying Rust/C code are surfaced as standard Java exceptions rather than causing crashes or security vulnerabilities.
  6. Implement Host Functions in Java

    main

    A host function is a Java function provided to a Wasm module to fulfill one of its imports. Because host functions run in the JVM, they are unrestricted and can perform any operation (like file I/O or network calls), effectively allowing the Wasm module to "escape the sandbox."

    Security Warning: Host functions act as a security boundary. If the Wasm code is untrusted, implement host functions carefully to prevent unauthorized access to the host environment.

    To define a HostFunction, you must provide:

    1. Namespace and Name: The module's import identifier (e.g., console and log).
    2. Function Type: The Wasm type signature (argument types and return types).
    3. Implementation: A lambda or function that executes when the Wasm module calls the import. This implementation receives an Instance object, which provides access to the Wasm module's linear memory.
    import com.dylibso.chicory.runtime.Instance;
    import com.dylibso.chicory.runtime.HostFunction;
    import com.dylibso.chicory.wasm.types.ValType;
    import com.dylibso.chicory.wasm.types.FunctionType;
    import java.util.List;
    
    var func = new HostFunction(
        "console",
        "log",
        FunctionType.of(
            List.of(ValType.I32, ValType.I32), // Arguments: length and offset
            List.of()                          // Return type: void
        ),
        (Instance instance, long... args) -> {
            var len = (int) args[0];
            var offset = (int) args[1];
            // Use instance.memory() to read data from the Wasm module's linear memory
            var message = instance.memory().readString(offset, len);
            System.out.println(message);
            return null;
        });
  7. Important considerations when using Store

    main

    When working with a Store, keep the following behaviors and limitations in mind:

    • Shorthand vs. Low-level API: store.instantiate("name", module) is a shorthand for retrieving current import values, building an instance with those values, and registering it. It is the recommended way to instantiate modules.
    • Name Collisions: Registering two instances with the same name will overwrite the previous instance's functions, globals, memories, and tables. For example, registering a second instance named "logger2" with a function logIt will overwrite any existing logger2.logIt.
    • Thread Safety: The Store is a mutable object and is not thread-safe. It is not intended to be shared across threads.
    • Dependency Ordering: The Store does not automatically resolve interdependencies between modules. If your modules depend on each other, you must instantiate and register them in the correct order.
  8. Explore experimental Chicory modules

    main

    Chicory provides several experimental modules for advanced use cases. These are released with the -experimental suffix and reside in the experimental namespace. They are not yet considered fully stable:

    • aot-experimental: An Ahead Of Time (AoT) translator that converts Wasm to Java Bytecode. It is very fast but requires reflection and depends on ASM.
    • aot-maven-plugin-experimental: A Maven plugin that uses the AoT translator at compile time to generate artifacts on disk, avoiding runtime reflection and external dependencies (though it sacrifices dynamic loading).
    • cli-experimental: A Command Line Interface for evaluating Chicory directly from the terminal.
    • host-module-annotations-experimental & host-module-processor-experimental: A pair of annotations and an annotation processor designed to help integrate Chicory via a higher-level, Java-idiomatic generated API.
  9. Chicory design goals and non-goals

    main

    Chicory is designed with specific trade-offs in mind to prioritize safety and ease of use over raw performance.

    Goals

    • Safety First: Willing to sacrifice performance for maximum safety and simplicity.
    • Portability: Easy to run Wasm in any JVM environment, including highly restrictive ones, without native code.
    • Spec Compliance: Full support for the core WebAssembly specification.
    • Idiomatic Integration: Easy and idiomatic integration with Java and other host languages.

    Non-Goals

    • Chicory is not intended to be a standalone runtime.
    • Chicory is not intended to be the fastest runtime available.
    • Chicory is not intended to be the right choice for every single JVM project.
  10. Understanding Host and Guest in Chicory

    main

    In the context of Chicory and WebAssembly (Wasm):

    • Guest: The Wasm module instance being executed.
    • Host: The surrounding runtime environment (e.g., your Java application using Chicory as a library).

    Wasm modules interact with the outside world through imports and exports. While a module can export functions to be called by the host, it must import functions to perform I/O or interact with other modules. Without imports, a Wasm module is limited to "pure compute" and cannot perform any I/O.

  11. Understand the core Chicory modules

    main

    Chicory is a pure Java WebAssembly runtime composed of several key modules that serve different purposes in the Wasm lifecycle:

    • wasm: The core module providing idiomatic Java APIs for working with arbitrary binary WebAssembly modules and handling the Wasm specification.
    • runtime: The main interpreter. It supports the full V1 WASM specification (excluding SIMD). It is designed to be extremely reliable, portable, and readable.
    • wasi: Provides an implementation of Wasi Preview 1, allowing Chicory to run real-world Wasm modules compiled from languages like Go, Rust, and C++.
    • log: Decouples logging from the Java Platform Logging (JEP 264), which is useful for environments like Android where JEP 264 is unavailable.
    • wabt: A bundled pure Java version of the WebAssembly Binary Toolkit (including wat2wasm and wast2json) provided as a Jar artifact.
    • bom: A Bill of Materials module used to manage dependency versions across the other modules.