Struct jni::JavaVM

source · []
#[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:

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:

  1. By JAVA_HOME environment variable, if it is set.
  2. 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 to PATH environment variable.
  • On MacOS, append the path to libjvm.dylib to LD_LIBRARY_PATH environment variable.
  • On Linux, append the path to libjvm.so to LD_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

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”.

Create a JavaVM from a raw pointer.

Safety

Expects a valid pointer retrieved from the JNI_CreateJavaVM JNI function. Only does null check.

Returns underlying sys::JavaVM interface.

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.

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.

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.

Returns the current number of threads attached to the JVM.

This method is provided mostly for diagnostic purposes.

Get the JNIEnv associated with the current thread, or ErrorKind::Detached if the current thread is not attached to the java VM.

Trait Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.