#[repr(transparent)]pub struct JavaVM(_);
Expand description
The Java VM, providing Invocation API support.
The JavaVM can be obtained either via JNIEnv#get_java_vm
in an already attached
thread, or it can be launched from Rust via JavaVM#new
.
Attaching Native Threads
A native thread must «attach» itself to be able to call Java methods outside of a native Java method. This library provides two modes of attachment, each ensuring the thread is promptly detached:
- A scoped attachment with
attach_current_thread
. The thread will automatically detach itself once the returned guard is dropped. - A permanent attachment with
attach_current_thread_permanently
orattach_current_thread_as_daemon
. The thread will automatically detach itself before it terminates.
As attachment and detachment of a thread is an expensive operation, the scoped attachment
shall be used if happens infrequently. If you have an undefined scope where you need
to use JNIEnv
and cannot keep the AttachGuard
, consider attaching the thread
permanently.
Local Reference Management
Remember that the native thread attached to the VM must manage the local references
properly, i.e., do not allocate an excessive number of references and release them promptly
when they are no longer needed to enable the GC to collect them. A common approach is to use
an appropriately-sized local frame for larger code fragments
(see with_local_frame
and Executor)
and auto locals in loops.
See also the JNI specification for details on referencing Java objects.
Executor
Jni-rs provides an Executor
— a helper struct that allows to
execute a closure with JNIEnv
. It combines the performance benefits of permanent attaches
and automatic local reference management. Prefer it to manual permanent attaches if
they happen in various parts of the code to reduce the burden of local reference management.
Launching JVM from Rust
To launch a JVM from a native process, enable the invocation
feature
in the Cargo.toml:
jni = { version = "0.19.0", features = ["invocation"] }
The application will require linking to the dynamic jvm
library, which is distributed
with the JVM, and allow to use JavaVM#new
:
// Build the VM properties
let jvm_args = InitArgsBuilder::new()
// Pass the JNI API version (default is 8)
.version(JNIVersion::V8)
// You can additionally pass any JVM options (standard, like a system property,
// or VM-specific).
// Here we enable some extra JNI checks useful during development
.option("-Xcheck:jni")
.build()
.unwrap();
// Create a new VM
let jvm = JavaVM::new(jvm_args)?;
// Attach the current thread to call into Java — see extra options in
// "Attaching Native Threads" section.
//
// This method returns the guard that will detach the current thread when dropped,
// also freeing any local references created in it
let env = jvm.attach_current_thread()?;
// Call Java Math#abs(-10)
let x = JValue::from(-10);
let val: jint = env.call_static_method("java/lang/Math", "abs", "(I)I", &[x])?
.i()?;
assert_eq!(val, 10);
During build time, the JVM installation path is determined:
- By
JAVA_HOME
environment variable, if it is set. - Otherwise — from
java
output.
It is recommended to set JAVA_HOME
to have reproducible builds,
especially, in case of multiple VMs installed.
At application run time, you must specify the path
to the jvm
library so that the loader can locate it.
- On Windows, append the path to
jvm.dll
toPATH
environment variable. - On MacOS, append the path to
libjvm.dylib
toLD_LIBRARY_PATH
environment variable. - On Linux, append the path to
libjvm.so
toLD_LIBRARY_PATH
environment variable.
The exact relative path to jvm
library is version-specific.
For more information on linking — see documentation in build.rs.
Implementations
sourceimpl JavaVM
impl JavaVM
sourcepub fn new(args: InitArgs) -> Result<Self>
pub fn new(args: InitArgs) -> Result<Self>
Launch a new JavaVM using the provided init args.
Unlike original JNI API, the main thread (the thread from which this method is called) will
not be attached to JVM. You must explicitly use attach_current_thread…
methods (refer
to Attaching Native Threads section).
This API requires “invocation” feature to be enabled, see “Launching JVM from Rust”.
sourcepub unsafe fn from_raw(ptr: *mut JavaVM) -> Result<Self>
pub unsafe fn from_raw(ptr: *mut JavaVM) -> Result<Self>
Create a JavaVM from a raw pointer.
Safety
Expects a valid pointer retrieved from the JNI_CreateJavaVM
JNI function. Only does null check.
sourcepub fn get_java_vm_pointer(&self) -> *mut JavaVM
pub fn get_java_vm_pointer(&self) -> *mut JavaVM
Returns underlying sys::JavaVM
interface.
sourcepub fn attach_current_thread_permanently(&self) -> Result<JNIEnv<'_>>
pub fn attach_current_thread_permanently(&self) -> Result<JNIEnv<'_>>
Attaches the current thread to the JVM. Calling this for a thread that is already attached is a no-op.
The thread will detach itself automatically when it exits.
Attached threads block JVM exit. If it is not desirable — consider using
attach_current_thread_as_daemon
.
sourcepub fn attach_current_thread(&self) -> Result<AttachGuard<'_>>
pub fn attach_current_thread(&self) -> Result<AttachGuard<'_>>
Attaches the current thread to the Java VM. The returned AttachGuard
can be dereferenced to a JNIEnv
and automatically detaches the thread
when dropped. Calling this in a thread that is already attached is a no-op, and
will neither change its daemon status nor prematurely detach it.
Attached threads block JVM exit.
Attaching and detaching a thread is an expensive operation. If you use it frequently
in the same threads, consider either attaching them permanently,
or, if the scope where you need the JNIEnv
is well-defined, keeping the returned guard.
sourcepub fn attach_current_thread_as_daemon(&self) -> Result<JNIEnv<'_>>
pub fn attach_current_thread_as_daemon(&self) -> Result<JNIEnv<'_>>
Attaches the current thread to the Java VM as a daemon. Calling this in a thread that is already attached is a no-op, and will not change its status to a daemon thread.
The thread will detach itself automatically when it exits.
sourcepub fn threads_attached(&self) -> usize
pub fn threads_attached(&self) -> usize
Returns the current number of threads attached to the JVM.
This method is provided mostly for diagnostic purposes.
Trait Implementations
Auto Trait Implementations
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more