Interoperability with Java
Java can load shared objects via
Java Native Interface (JNI).
The jni crate allows you to create a compatible
library.
First, we create a Rust function to export to Java:
interoperability/java/src/lib.rs:
#![allow(unused)] fn main() { //! Rust <-> Java FFI demo. use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; /// HelloWorld::hello method implementation. // SAFETY: There is no other global function of this name. #[unsafe(no_mangle)] pub extern "system" fn Java_HelloWorld_hello( mut env: JNIEnv, _class: JClass, name: JString, ) -> jstring { let input: String = env.get_string(&name).unwrap().into(); let greeting = format!("Hello, {input}!"); let output = env.new_string(greeting).unwrap(); output.into_raw() } }
interoperability/java/Android.bp:
rust_ffi_shared {
    name: "libhello_jni",
    crate_name: "hello_jni",
    srcs: ["src/lib.rs"],
    rustlibs: ["libjni"],
}
We then call this function from Java:
interoperability/java/HelloWorld.java:
class HelloWorld {
    private static native String hello(String name);
    static {
        System.loadLibrary("hello_jni");
    }
    public static void main(String[] args) {
        String output = HelloWorld.hello("Alice");
        System.out.println(output);
    }
}
interoperability/java/Android.bp:
java_binary {
    name: "helloworld_jni",
    srcs: ["HelloWorld.java"],
    main_class: "HelloWorld",
    jni_libs: ["libhello_jni"],
}
Finally, you can build, sync, and run the binary:
m helloworld_jni
adb sync  # requires adb root && adb remount
adb shell /system/bin/helloworld_jni
- 
The unsafe(no_mangle)attribute instructs Rust to emit theJava_HelloWorld_hellosymbol exactly as written. This is important so that Java can recognize the symbol as ahellomethod on theHelloWorldclass.- By default, Rust will mangle (rename) symbols so that a binary can link in two versions of the same Rust crate.