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:

  1. #![allow(unused)]
  2. fn main() {
  3. //! Rust <-> Java FFI demo.
  4. use jni::objects::{JClass, JString};
  5. use jni::sys::jstring;
  6. use jni::JNIEnv;
  7. /// HelloWorld::hello method implementation.
  8. #[no_mangle]
  9. pub extern "system" fn Java_HelloWorld_hello(
  10. env: JNIEnv,
  11. _class: JClass,
  12. name: JString,
  13. ) -> jstring {
  14. let input: String = env.get_string(name).unwrap().into();
  15. let greeting = format!("Hello, {input}!");
  16. let output = env.new_string(greeting).unwrap();
  17. output.into_inner()
  18. }
  19. }

interoperability/java/Android.bp:

rust_ffi_shared { name: "libhello_jni", crate_name: "hello_jni", srcs: ["src/lib.rs"], rustlibs: ["libjni"], }

Finally, we can 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", required: ["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