jni-simple
This crate contains a simple dumb handwritten rust wrapper around the JNI (Java Native Interface) API. It does absolutely no magic around the JNI Calls and lets you just use it as you would in C.
This crate is an early work in progress and may contain bugs or missing features.
If you need something production ready I recommend using the jni crate.
Examples
Loading a JVM on from a shared object file or dll
Note: this example assumes the loadjvm feature is enabled!
use ;
use null;
Writing a JNI shared library that implements a native method
The complete version of this example can be found in the repository in the example_project folder.
use Write;
use ;
use ;
use ;
use thread;
use Duration;
use stdout;
//Optional: Only needed if you need to spawn "rust" threads that need to interact with the JVM.
extern "system"
pub unsafe extern "system"
//Would be called from java. the signature in java is org.example.JNITest#test()
pub unsafe extern "system"
Main goals of this crate
Dont pretend that JNI is "safe"
JNI is inherently unsafe (from a rust point of view) and any attempt to enforce safety will lead performance or API complexity issues. All JNI methods provided by this crate are marked as "unsafe" as they should be.
Simple type system of JNI is kept as is
All types like jobject, jstring, jarray,... which are opaque handles represented as pointers in C are represented as raw opaque pointers in Rust that are type aliases of each other. This essentially makes them just hint to the user and doesn't enforce any type safety as that would sometimes be a big hindrance when working with JNI.
Designed for runtime dynamic linking of the JVM
While there are some ways of statically linking a JVM into the binary, they are usually cumbersome, poorly documented and rarely tested. Alternatively one can provide the JVM on the linker path so ldd can find it, but I have never seen this occur in the real world.
This crate is developed for the more common use case that the JVM is available somewhere on the system and leaves it up to the user of the crate to write the necessary code to find and load the JVM.
This allows for maximum flexibility when writing a launcher app which for example may first download a JVM from the internet.
As should be obvious, when writing a native library that does not launch the JVM itself because it's a library
implementing some native methods and loaded by System.load or System.loadLibrary then this is irrelevant.
Features
loadjvm
This feature provides functions to dynamically link the jvm using the libloading crate
from a string containing the absolute path to libjvm.so or jvm.dll.
Note: If you do not want to use the libloading create but still start the JVM then there are methods provided to
load the JVM from a pointer to JNI_CreateJavaVM function instead of a dll/so file,
if you want to do dynamic linking yourself using dlopen or LoadLibraryA for example.
Note: This feature should not be used when writing a library that is loaded by System.load or System.loadLibrary.
It would just add a dependency that is not needed.
asserts
This feature enables assertions in the code. This is useful for debugging and testing purposes.
As mentioned above these checks will cause a big performance hit and should not be used in production code.
This feature should NOT be used with -Xcheck:jni as these checks contain calls to env.ExceptionCheck() which will
fool the JVM into thinking that your user code checks for exceptions, which it may not do.
I recommend using this feature before or after you have tested your code with -Xcheck:jni depending
on what problem your troubleshooting. The assertions are generally much better at detecting things like null pointers
or invalid parameters than the JVM checks, while the JVM checks are able to catch missing exception checks.