risingwave_jni_core

Struct EnvParam

source
#[repr(C)]
pub struct EnvParam<'a> { pub(crate) env: JNIEnv<'a>, pub(crate) class: JClass<'a>, }
Expand description

In most Jni interfaces, the first parameter is JNIEnv, and the second parameter is JClass. This struct simply encapsulates the two common parameters into a single struct for simplicity.

Fields§

§env: JNIEnv<'a>§class: JClass<'a>

Implementations§

source§

impl<'a> EnvParam<'a>

source

pub fn get_class(&self) -> &JClass<'a>

Methods from Deref<Target = JNIEnv<'a>>§

pub fn get_raw(&self) -> *mut *const JNINativeInterface_

Get the raw JNIEnv pointer

pub unsafe fn unsafe_clone(&self) -> JNIEnv<'local>

Duplicates this JNIEnv.

§Safety

The duplicate JNIEnv must not be used to create any local references, unless they are discarded before the current local reference frame is exited. Otherwise, they may have a lifetime longer than they are actually valid for, resulting in a use-after-free bug and undefined behavior.

See issue #392 for background.

pub fn get_version(&self) -> Result<JNIVersion, Error>

Get the java version that we’re being executed from.

pub fn define_class<S>( &mut self, name: S, loader: &JObject<'_>, buf: &[u8], ) -> Result<JClass<'local>, Error>
where S: Into<JNIString>,

Load a class from a buffer of raw class data. The name of the class must match the name encoded within the class file data.

pub fn define_unnamed_class( &mut self, loader: &JObject<'_>, buf: &[u8], ) -> Result<JClass<'local>, Error>

Load a class from a buffer of raw class data. The name of the class is inferred from the buffer.

pub fn define_class_bytearray<S>( &mut self, name: S, loader: &JObject<'_>, buf: &AutoElements<'_, '_, '_, i8>, ) -> Result<JClass<'local>, Error>
where S: Into<JNIString>,

Load a class from a buffer of raw class data. The name of the class must match the name encoded within the class file data.

pub fn find_class<S>(&mut self, name: S) -> Result<JClass<'local>, Error>
where S: Into<JNIString>,

Look up a class by name.

§Example
let class: JClass<'local> = env.find_class("java/lang/String")?;

pub fn get_superclass<'other_local, T>( &mut self, class: T, ) -> Result<Option<JClass<'local>>, Error>
where T: Desc<'local, JClass<'other_local>>,

Returns the superclass for a particular class. Returns None for java.lang.Object or an interface. As with [Self::find_class], takes a descriptor

§Errors

If a JNI call fails

pub fn is_assignable_from<'other_local_1, 'other_local_2, T, U>( &mut self, class1: T, class2: U, ) -> Result<bool, Error>
where T: Desc<'local, JClass<'other_local_1>>, U: Desc<'local, JClass<'other_local_2>>,

Tests whether class1 is assignable from class2.

pub fn is_instance_of<'other_local_1, 'other_local_2, O, T>( &mut self, object: O, class: T, ) -> Result<bool, Error>
where O: AsRef<JObject<'other_local_1>>, T: Desc<'local, JClass<'other_local_2>>,

Returns true if the object reference can be cast to the given type.

NB: Unlike the operator instanceof, function IsInstanceOf returns true for all classes if object is null.

See JNI documentation for details.

pub fn is_same_object<'other_local_1, 'other_local_2, O, T>( &self, ref1: O, ref2: T, ) -> Result<bool, Error>
where O: AsRef<JObject<'other_local_1>>, T: AsRef<JObject<'other_local_2>>,

Returns true if ref1 and ref2 refer to the same Java object, or are both NULL. Otherwise, returns false.

pub fn throw<'other_local, E>(&mut self, obj: E) -> Result<(), Error>
where E: Desc<'local, JThrowable<'other_local>>,

Raise an exception from an existing object. This will continue being thrown in java unless exception_clear is called.

§Examples
env.throw(("java/lang/Exception", "something bad happened"))?;

Defaulting to “java/lang/Exception”:

env.throw("something bad happened")?;

pub fn throw_new<'other_local, S, T>( &mut self, class: T, msg: S, ) -> Result<(), Error>
where S: Into<JNIString>, T: Desc<'local, JClass<'other_local>>,

Create and throw a new exception from a class descriptor and an error message.

§Example
env.throw_new("java/lang/Exception", "something bad happened")?;

pub fn exception_occurred(&mut self) -> Result<JThrowable<'local>, Error>

Check whether or not an exception is currently in the process of being thrown. An exception is in this state from the time it gets thrown and not caught in a java function until exception_clear is called.

pub fn exception_describe(&self) -> Result<(), Error>

Print exception information to the console.

pub fn exception_clear(&self) -> Result<(), Error>

Clear an exception in the process of being thrown. If this is never called, the exception will continue being thrown when control is returned to java.

pub fn fatal_error<S>(&self, msg: S) -> !
where S: Into<JNIString>,

Abort the JVM with an error message.

pub fn exception_check(&self) -> Result<bool, Error>

Check to see if an exception is being thrown. This only differs from exception_occurred in that it doesn’t return the actual thrown exception.

pub unsafe fn new_direct_byte_buffer( &mut self, data: *mut u8, len: usize, ) -> Result<JByteBuffer<'local>, Error>

Create a new instance of a direct java.nio.ByteBuffer

§Example
let buf = vec![0; 1024 * 1024];
let (addr, len) = { // (use buf.into_raw_parts() on nightly)
    let buf = buf.leak();
    (buf.as_mut_ptr(), buf.len())
};
let direct_buffer = unsafe { env.new_direct_byte_buffer(addr, len) }?;
§Safety

Expects a valid (non-null) pointer and length

Caller must ensure the lifetime of data extends to all uses of the returned ByteBuffer. The JVM may maintain references to the ByteBuffer beyond the lifetime of this JNIEnv.

pub fn get_direct_buffer_address( &self, buf: &JByteBuffer<'_>, ) -> Result<*mut u8, Error>

Returns the starting address of the memory of the direct java.nio.ByteBuffer.

pub fn get_direct_buffer_capacity( &self, buf: &JByteBuffer<'_>, ) -> Result<usize, Error>

Returns the capacity (length) of the direct java.nio.ByteBuffer.

§Terminology

“capacity” here means the length that was passed to [Self::new_direct_byte_buffer()] which does not reflect the (potentially) larger size of the underlying allocation (unlike the Vec API).

The terminology is simply kept from the original JNI API (GetDirectBufferCapacity).

pub fn new_global_ref<'other_local, O>( &self, obj: O, ) -> Result<GlobalRef, Error>
where O: AsRef<JObject<'other_local>>,

Turns an object into a global ref. This has the benefit of removing the lifetime bounds since it’s guaranteed to not get GC’d by java. It releases the GC pin upon being dropped.

pub fn new_weak_ref<'other_local, O>( &self, obj: O, ) -> Result<Option<WeakRef>, Error>
where O: AsRef<JObject<'other_local>>,

Creates a new [weak global reference][WeakRef].

If the provided object is null, this method returns None. Otherwise, it returns Some containing the new weak global reference.

pub fn new_local_ref<'other_local, O>( &self, obj: O, ) -> Result<JObject<'local>, Error>
where O: AsRef<JObject<'other_local>>,

Create a new local reference to an object.

Specifically, this calls the JNI function NewLocalRef, which creates a reference in the current local reference frame, regardless of whether the original reference belongs to the same local reference frame, a different one, or is a [global reference][GlobalRef]. In Rust terms, this method accepts a JNI reference with any valid lifetime and produces a clone of that reference with the lifetime of this JNIEnv. The returned reference can outlive the original.

This method is useful when you have a strong global reference and you can’t prevent it from being dropped before you’re finished with it. In that case, you can use this method to create a new local reference that’s guaranteed to remain valid for the duration of the current local reference frame, regardless of what later happens to the original global reference.

§Lifetimes

'local is the lifetime of the local reference frame that this JNIEnv belongs to. This method creates a new local reference in that frame, with lifetime 'local.

'other_local is the lifetime of the original reference’s frame. It can be any valid lifetime, even one that 'local outlives or vice versa.

Think of 'local as meaning 'new and 'other_local as meaning 'original. (It is unfortunately not possible to actually give these names to the two lifetimes because 'local is a parameter to the JNIEnv type, not a parameter to this method.)

§Example

In the following example, the ExampleError::extract_throwable method uses JNIEnv::new_local_ref to create a new local reference that outlives the original global reference:

/// An error that may be caused by either a Java exception or something going wrong in Rust
/// code.
enum ExampleError {
    /// This variant represents a Java exception.
    ///
    /// The enclosed `GlobalRef` points to a Java object of class `java.lang.Throwable`
    /// (or one of its many subclasses).
    Exception(GlobalRef),

    /// This variant represents an error in Rust code, not a Java exception.
    Other(SomeOtherErrorType),
}

impl ExampleError {
    /// Consumes this `ExampleError` and produces a `JThrowable`, suitable for throwing
    /// back to Java code.
    ///
    /// If this is an `ExampleError::Exception`, then this extracts the enclosed Java
    /// exception object. Otherwise, a new exception object is created to represent this
    /// error.
    fn extract_throwable<'local>(self, env: &mut JNIEnv<'local>) -> jni::errors::Result<JThrowable<'local>> {
        let throwable: JObject = match self {
            ExampleError::Exception(exception) => {
                // The error was caused by a Java exception.

                // Here, `exception` is a `GlobalRef` pointing to a Java `Throwable`. It
                // will be dropped at the end of this `match` arm. We'll use
                // `new_local_ref` to create a local reference that will outlive the
                // `GlobalRef`.

                env.new_local_ref(&exception)?
            }

            ExampleError::Other(error) => {
                // The error was caused by something that happened in Rust code. Create a
                // new `java.lang.Error` to represent it.

                let error_string = env.new_string(error.to_string())?;

                env.new_object(
                    "java/lang/Error",
                    "(Ljava/lang/String;)V",
                    &[
                        (&error_string).into(),
                    ],
                )?
            }
        };

        Ok(JThrowable::from(throwable))
    }
}

pub fn auto_local<O>(&self, obj: O) -> AutoLocal<'local, O>
where O: Into<JObject<'local>>,

Creates a new auto-deleted local reference.

See also with_local_frame method that can be more convenient when you create a bounded number of local references but cannot rely on automatic de-allocation (e.g., in case of recursion, deep call stacks, permanently-attached native threads, etc.).

pub fn delete_local_ref<'other_local, O>(&self, obj: O) -> Result<(), Error>
where O: Into<JObject<'other_local>>,

Deletes the local reference.

Local references are valid for the duration of a native method call. They are freed automatically after the native method returns. Each local reference costs some amount of Java Virtual Machine resource. Programmers need to make sure that native methods do not excessively allocate local references. Although local references are automatically freed after the native method returns to Java, excessive allocation of local references may cause the VM to run out of memory during the execution of a native method.

In most cases it is better to use AutoLocal (see auto_local method) or with_local_frame instead of direct delete_local_ref calls.

obj can be a mutable borrow of a local reference (such as &mut JObject) instead of the local reference itself (such as JObject). In this case, the local reference will still exist after this method returns, but it will be null.

pub fn push_local_frame(&self, capacity: i32) -> Result<(), Error>

Creates a new local reference frame, in which at least a given number of local references can be created.

Returns Err on failure, with a pending OutOfMemoryError.

Prefer to use with_local_frame instead of direct push_local_frame/pop_local_frame calls.

See also auto_local method and AutoLocal type — that approach can be more convenient in loops.

pub unsafe fn pop_local_frame( &self, result: &JObject<'_>, ) -> Result<JObject<'local>, Error>

Pops off the current local reference frame, frees all the local references allocated on the current stack frame, except the result, which is returned from this function and remains valid.

The resulting JObject will be NULL iff result is NULL.

This method allows direct control of local frames, but it can cause undefined behavior and is therefore unsafe. Prefer [JNIEnv::with_local_frame] instead.

§Safety

Any local references created after the most recent call to [JNIEnv::push_local_frame] (or the underlying JNI function) must not be used after calling this method.

pub fn with_local_frame<F, T, E>(&mut self, capacity: i32, f: F) -> Result<T, E>
where F: FnOnce(&mut JNIEnv<'_>) -> Result<T, E>, E: From<Error>,

Executes the given function in a new local reference frame, in which at least a given number of references can be created. Once this method returns, all references allocated in the frame are freed.

If a frame can’t be allocated with the requested capacity for local references, returns Err with a pending OutOfMemoryError.

Since local references created within this frame won’t be accessible to the calling frame then if you need to pass an object back to the caller then you can do that via a [GlobalRef] / [Self::make_global].

pub fn with_local_frame_returning_local<F, E>( &mut self, capacity: i32, f: F, ) -> Result<JObject<'local>, E>
where F: for<'new_local> FnOnce(&mut JNIEnv<'new_local>) -> Result<JObject<'new_local>, E>, E: From<Error>,

Executes the given function in a new local reference frame, in which at least a given number of references can be created. Once this method returns, all references allocated in the frame are freed, except the one that the function returns, which remains valid.

If a frame can’t be allocated with the requested capacity for local references, returns Err with a pending OutOfMemoryError.

Since the low-level JNI interface has support for passing back a single local reference from a local frame as special-case optimization, this alternative to with_local_frame exposes that capability to return a local reference without needing to create a temporary [GlobalRef].

pub fn alloc_object<'other_local, T>( &mut self, class: T, ) -> Result<JObject<'local>, Error>
where T: Desc<'local, JClass<'other_local>>,

Allocates a new object from a class descriptor without running a constructor.

pub fn get_method_id<'other_local, T, U, V>( &mut self, class: T, name: U, sig: V, ) -> Result<JMethodID, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString>, V: Into<JNIString>,

Look up a method by class descriptor, name, and signature.

§Example
let method_id: JMethodID =
    env.get_method_id("java/lang/String", "substring", "(II)Ljava/lang/String;")?;

pub fn get_static_method_id<'other_local, T, U, V>( &mut self, class: T, name: U, sig: V, ) -> Result<JStaticMethodID, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString>, V: Into<JNIString>,

Look up a static method by class descriptor, name, and signature.

§Example
let method_id: JStaticMethodID =
    env.get_static_method_id("java/lang/String", "valueOf", "(I)Ljava/lang/String;")?;

pub fn get_field_id<'other_local, T, U, V>( &mut self, class: T, name: U, sig: V, ) -> Result<JFieldID, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString>, V: Into<JNIString>,

Look up the field ID for a class/name/type combination.

§Example
let field_id: JFieldID = env.get_field_id("com/my/Class", "intField", "I")?;

pub fn get_static_field_id<'other_local, T, U, V>( &mut self, class: T, name: U, sig: V, ) -> Result<JStaticFieldID, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString>, V: Into<JNIString>,

Look up the static field ID for a class/name/type combination.

§Example
let field_id: JStaticFieldID = env.get_static_field_id("com/my/Class", "intField", "I")?;

pub fn get_object_class<'other_local, O>( &self, obj: O, ) -> Result<JClass<'local>, Error>
where O: AsRef<JObject<'other_local>>,

Get the class for an object.

pub unsafe fn call_static_method_unchecked<'other_local, T, U>( &mut self, class: T, method_id: U, ret: ReturnType, args: &[jvalue], ) -> Result<JValueGen<JObject<'local>>, Error>
where T: Desc<'local, JClass<'other_local>>, U: Desc<'local, JStaticMethodID>,

Call a static method in an unsafe manner. This does nothing to check whether the method is valid to call on the class, whether the return type is correct, or whether the number of args is valid for the method.

Under the hood, this simply calls the CallStatic<Type>MethodA method with the provided arguments.

§Safety

The provided JMethodID must be valid, and match the types and number of arguments, and return type. If these are incorrect, the JVM may crash. The JMethodID must also match the passed type.

pub unsafe fn call_method_unchecked<'other_local, O, T>( &mut self, obj: O, method_id: T, ret: ReturnType, args: &[jvalue], ) -> Result<JValueGen<JObject<'local>>, Error>
where O: AsRef<JObject<'other_local>>, T: Desc<'local, JMethodID>,

Call an object method in an unsafe manner. This does nothing to check whether the method is valid to call on the object, whether the return type is correct, or whether the number of args is valid for the method.

Under the hood, this simply calls the Call<Type>MethodA method with the provided arguments.

§Safety

The provided JMethodID must be valid, and match the types and number of arguments, and return type. If these are incorrect, the JVM may crash. The JMethodID must also match the passed type.

pub fn call_method<'other_local, O, S, T>( &mut self, obj: O, name: S, sig: T, args: &[JValueGen<&JObject<'_>>], ) -> Result<JValueGen<JObject<'local>>, Error>
where O: AsRef<JObject<'other_local>>, S: Into<JNIString>, T: Into<JNIString> + AsRef<str>,

Calls an object method safely. This comes with a number of lookups/checks. It

  • Parses the type signature to find the number of arguments and return type
  • Looks up the JClass for the given object.
  • Looks up the JMethodID for the class/name/signature combination
  • Ensures that the number/types of args matches the signature
    • Cannot check an object’s type - but primitive types are matched against each other (including Object)
  • Calls call_method_unchecked with the verified safe arguments.

Note: this may cause a Java exception if the arguments are the wrong type, in addition to if the method itself throws.

pub fn call_static_method<'other_local, T, U, V>( &mut self, class: T, name: U, sig: V, args: &[JValueGen<&JObject<'_>>], ) -> Result<JValueGen<JObject<'local>>, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString>, V: Into<JNIString> + AsRef<str>,

Calls a static method safely. This comes with a number of lookups/checks. It

  • Parses the type signature to find the number of arguments and return type
  • Looks up the JMethodID for the class/name/signature combination
  • Ensures that the number/types of args matches the signature
    • Cannot check an object’s type - but primitive types are matched against each other (including Object)
  • Calls call_method_unchecked with the verified safe arguments.

Note: this may cause a Java exception if the arguments are the wrong type, in addition to if the method itself throws.

pub fn new_object<'other_local, T, U>( &mut self, class: T, ctor_sig: U, ctor_args: &[JValueGen<&JObject<'_>>], ) -> Result<JObject<'local>, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString> + AsRef<str>,

Create a new object using a constructor. This is done safely using checks similar to those in call_static_method.

pub unsafe fn new_object_unchecked<'other_local, T>( &mut self, class: T, ctor_id: JMethodID, ctor_args: &[jvalue], ) -> Result<JObject<'local>, Error>
where T: Desc<'local, JClass<'other_local>>,

Create a new object using a constructor. Arguments aren’t checked because of the JMethodID usage.

§Safety

The provided JMethodID must be valid, and match the types and number of arguments, as well as return type (always an Object for a constructor). If these are incorrect, the JVM may crash. The JMethodID must also match the passed type.

pub fn get_list<'other_local_1, 'obj_ref>( &mut self, obj: &'obj_ref JObject<'other_local_1>, ) -> Result<JList<'local, 'other_local_1, 'obj_ref>, Error>
where 'other_local_1: 'obj_ref,

Cast a JObject to a JList. This won’t throw exceptions or return errors in the event that the object isn’t actually a list, but the methods on the resulting map object will.

pub fn get_map<'other_local_1, 'obj_ref>( &mut self, obj: &'obj_ref JObject<'other_local_1>, ) -> Result<JMap<'local, 'other_local_1, 'obj_ref>, Error>
where 'other_local_1: 'obj_ref,

Cast a JObject to a JMap. This won’t throw exceptions or return errors in the event that the object isn’t actually a map, but the methods on the resulting map object will.

pub unsafe fn get_string_unchecked<'other_local, 'obj_ref>( &self, obj: &'obj_ref JString<'other_local>, ) -> Result<JavaStr<'local, 'other_local, 'obj_ref>, Error>
where 'other_local: 'obj_ref,

Get a [JavaStr] from a [JString]. This allows conversions from java string objects to rust strings.

This only entails calling GetStringUTFChars, which will return a [JavaStr] in Java’s Modified UTF-8 format.

This doesn’t automatically decode Java’s modified UTF-8 format but you can use .into() to convert the returned [JavaStr] into a Rust String.

§Safety

The caller must guarantee that the Object passed in is an instance of java.lang.String, passing in anything else will lead to undefined behaviour (The JNI implementation is likely to crash or abort the process).

§Errors

Returns an error if obj is null

pub fn get_string<'other_local, 'obj_ref>( &mut self, obj: &'obj_ref JString<'other_local>, ) -> Result<JavaStr<'local, 'other_local, 'obj_ref>, Error>
where 'other_local: 'obj_ref,

Get a [JavaStr] from a [JString]. This allows conversions from java string objects to rust strings.

This entails checking that the given object is a java.lang.String and calling GetStringUTFChars, which will return a [JavaStr] in Java’s Modified UTF-8 format.

This doesn’t automatically decode Java’s modified UTF-8 format but you can use .into() to convert the returned [JavaStr] into a Rust String.

§Performance

This function has a large relative performance impact compared to [Self::get_string_unchecked]. For example it may be about five times slower than get_string_unchecked for very short string. This performance penalty comes from the extra validation performed by this function. If and only if you can guarantee that your obj is of java.lang.String, use [Self::get_string_unchecked].

§Errors

Returns an error if obj is null or is not an instance of java.lang.String

pub fn new_string<S>(&self, from: S) -> Result<JString<'local>, Error>
where S: Into<JNIString>,

Create a new java string object from a rust string. This requires a re-encoding of rusts real UTF-8 strings to java’s modified UTF-8 format.

pub fn get_array_length<'other_local, 'array>( &self, array: &'array impl AsJArrayRaw<'other_local>, ) -> Result<i32, Error>

Get the length of a [JPrimitiveArray] or [JObjectArray].

pub fn new_object_array<'other_local_1, 'other_local_2, T, U>( &mut self, length: i32, element_class: T, initial_element: U, ) -> Result<JObjectArray<'local>, Error>
where T: Desc<'local, JClass<'other_local_2>>, U: AsRef<JObject<'other_local_1>>,

Construct a new array holding objects in class element_class. All elements are initially set to initial_element.

This function returns a local reference, that must not be allocated excessively. See Java documentation for details.

pub fn get_object_array_element<'other_local>( &mut self, array: impl AsRef<JObjectArray<'other_local>>, index: i32, ) -> Result<JObject<'local>, Error>

Returns a local reference to an element of the [JObjectArray] array.

pub fn set_object_array_element<'other_local_1, 'other_local_2>( &self, array: impl AsRef<JObjectArray<'other_local_1>>, index: i32, value: impl AsRef<JObject<'other_local_2>>, ) -> Result<(), Error>

Sets an element of the [JObjectArray] array.

pub fn byte_array_from_slice( &self, buf: &[u8], ) -> Result<JPrimitiveArray<'local, i8>, Error>

Create a new java byte array from a rust byte slice.

pub fn convert_byte_array<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i8>>, ) -> Result<Vec<u8>, Error>

Converts a java byte array to a rust vector of bytes.

pub fn new_boolean_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, u8>, Error>

Create a new java boolean array of supplied length.

pub fn new_byte_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, i8>, Error>

Create a new java byte array of supplied length.

pub fn new_char_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, u16>, Error>

Create a new java char array of supplied length.

pub fn new_short_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, i16>, Error>

Create a new java short array of supplied length.

pub fn new_int_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, i32>, Error>

Create a new java int array of supplied length.

pub fn new_long_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, i64>, Error>

Create a new java long array of supplied length.

pub fn new_float_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, f32>, Error>

Create a new java float array of supplied length.

pub fn new_double_array( &self, length: i32, ) -> Result<JPrimitiveArray<'local, f64>, Error>

Create a new java double array of supplied length.

pub fn get_boolean_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, u8>>, start: i32, buf: &mut [u8], ) -> Result<(), Error>

Copy elements of the java boolean array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_byte_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i8>>, start: i32, buf: &mut [i8], ) -> Result<(), Error>

Copy elements of the java byte array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_char_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, u16>>, start: i32, buf: &mut [u16], ) -> Result<(), Error>

Copy elements of the java char array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_short_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i16>>, start: i32, buf: &mut [i16], ) -> Result<(), Error>

Copy elements of the java short array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_int_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i32>>, start: i32, buf: &mut [i32], ) -> Result<(), Error>

Copy elements of the java int array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_long_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i64>>, start: i32, buf: &mut [i64], ) -> Result<(), Error>

Copy elements of the java long array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_float_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, f32>>, start: i32, buf: &mut [f32], ) -> Result<(), Error>

Copy elements of the java float array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn get_double_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, f64>>, start: i32, buf: &mut [f64], ) -> Result<(), Error>

Copy elements of the java double array from the start index to the buf slice. The number of copied elements is equal to the buf length.

§Errors

If start is negative or start + buf.len() is greater than array.length then no elements are copied, an ArrayIndexOutOfBoundsException is thrown, and Err is returned.

pub fn set_boolean_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, u8>>, start: i32, buf: &[u8], ) -> Result<(), Error>

Copy the contents of the buf slice to the java boolean array at the start index.

pub fn set_byte_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i8>>, start: i32, buf: &[i8], ) -> Result<(), Error>

Copy the contents of the buf slice to the java byte array at the start index.

pub fn set_char_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, u16>>, start: i32, buf: &[u16], ) -> Result<(), Error>

Copy the contents of the buf slice to the java char array at the start index.

pub fn set_short_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i16>>, start: i32, buf: &[i16], ) -> Result<(), Error>

Copy the contents of the buf slice to the java short array at the start index.

pub fn set_int_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i32>>, start: i32, buf: &[i32], ) -> Result<(), Error>

Copy the contents of the buf slice to the java int array at the start index.

pub fn set_long_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, i64>>, start: i32, buf: &[i64], ) -> Result<(), Error>

Copy the contents of the buf slice to the java long array at the start index.

pub fn set_float_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, f32>>, start: i32, buf: &[f32], ) -> Result<(), Error>

Copy the contents of the buf slice to the java float array at the start index.

pub fn set_double_array_region<'other_local>( &self, array: impl AsRef<JPrimitiveArray<'other_local, f64>>, start: i32, buf: &[f64], ) -> Result<(), Error>

Copy the contents of the buf slice to the java double array at the start index.

pub fn get_field_unchecked<'other_local, O, T>( &mut self, obj: O, field: T, ty: ReturnType, ) -> Result<JValueGen<JObject<'local>>, Error>
where O: AsRef<JObject<'other_local>>, T: Desc<'local, JFieldID>,

Get a field without checking the provided type against the actual field.

pub fn set_field_unchecked<'other_local, O, T>( &mut self, obj: O, field: T, val: JValueGen<&JObject<'_>>, ) -> Result<(), Error>
where O: AsRef<JObject<'other_local>>, T: Desc<'local, JFieldID>,

Set a field without any type checking.

pub fn get_field<'other_local, O, S, T>( &mut self, obj: O, name: S, ty: T, ) -> Result<JValueGen<JObject<'local>>, Error>
where O: AsRef<JObject<'other_local>>, S: Into<JNIString>, T: Into<JNIString> + AsRef<str>,

Get a field. Requires an object class lookup and a field id lookup internally.

pub fn set_field<'other_local, O, S, T>( &mut self, obj: O, name: S, ty: T, val: JValueGen<&JObject<'_>>, ) -> Result<(), Error>
where O: AsRef<JObject<'other_local>>, S: Into<JNIString>, T: Into<JNIString> + AsRef<str>,

Set a field. Does the same lookups as get_field and ensures that the type matches the given value.

pub fn get_static_field_unchecked<'other_local, T, U>( &mut self, class: T, field: U, ty: JavaType, ) -> Result<JValueGen<JObject<'local>>, Error>
where T: Desc<'local, JClass<'other_local>>, U: Desc<'local, JStaticFieldID>,

Get a static field without checking the provided type against the actual field.

pub fn get_static_field<'other_local, T, U, V>( &mut self, class: T, field: U, sig: V, ) -> Result<JValueGen<JObject<'local>>, Error>
where T: Desc<'local, JClass<'other_local>>, U: Into<JNIString>, V: Into<JNIString> + AsRef<str>,

Get a static field. Requires a class lookup and a field id lookup internally.

pub fn set_static_field<'other_local, T, U>( &mut self, class: T, field: U, value: JValueGen<&JObject<'_>>, ) -> Result<(), Error>
where T: Desc<'local, JClass<'other_local>>, U: Desc<'local, JStaticFieldID>,

Set a static field. Requires a class lookup and a field id lookup internally.

pub unsafe fn set_rust_field<'other_local, O, S, T>( &mut self, obj: O, field: S, rust_object: T, ) -> Result<(), Error>
where O: AsRef<JObject<'other_local>>, S: AsRef<str>, T: Send + 'static,

Surrenders ownership of a Rust value to Java.

This requires an object with a long field to store the pointer.

In Java the property may look like:

private long myRustValueHandle = 0;

Or, in Kotlin the property may look like:

private var myRustValueHandle: Long = 0

Note that private properties are accessible to JNI which may be preferable to avoid exposing the handles to more code than necessary (since the handles are usually only meaningful to Rust code).

The Rust value will be implicitly wrapped in a Box<Mutex<T>>.

The Java object will be locked while changing the field value.

§Safety

It’s important to note that using this API will leak memory if [Self::take_rust_field] is never called so that the Rust type may be dropped.

One suggestion that may help ensure that a set Rust field will be cleaned up later is for the Java object to implement Closeable and let people use a use block (Kotlin) or try-with-resources (Java).

DO NOT make a copy of the handle stored in one of these fields since that could lead to a use-after-free error if the Rust type is taken and dropped multiple times from Rust. If you need to copy an object with one of these fields then the field should be zero initialized in the copy.

pub unsafe fn get_rust_field<'other_local, O, S, T>( &mut self, obj: O, field: S, ) -> Result<MutexGuard<'_, T>, Error>
where O: AsRef<JObject<'other_local>>, S: Into<JNIString>, T: Send + 'static,

Gets a lock on a Rust value that’s been given to a Java object.

Java still retains ownership and [Self::take_rust_field] will still need to be called at some point.

The Java object will be locked before reading the field value but the Java object lock will be released after the Rust Mutex lock for the field value has been taken (i.e the Java object won’t be locked once this function returns).

§Safety

Checks for a null pointer, but assumes that the data it points to is valid for T.

pub unsafe fn take_rust_field<'other_local, O, S, T>( &mut self, obj: O, field: S, ) -> Result<T, Error>
where O: AsRef<JObject<'other_local>>, S: AsRef<str>, T: Send + 'static,

Take a Rust field back from Java.

It sets the field to a null pointer to signal that it’s empty.

The Java object will be locked before taking the field value.

§Safety

This will make sure that the pointer is non-null, but still assumes that the data it points to is valid for T.

pub fn lock_obj<'other_local, O>( &self, obj: O, ) -> Result<MonitorGuard<'local>, Error>
where O: AsRef<JObject<'other_local>>,

Lock a Java object. The MonitorGuard that this returns is responsible for ensuring that it gets unlocked.

pub fn get_native_interface(&self) -> *mut *const JNINativeInterface_

Returns underlying sys::JNIEnv interface.

pub fn get_java_vm(&self) -> Result<JavaVM, Error>

Returns the Java VM interface.

pub fn ensure_local_capacity(&self, capacity: i32) -> Result<(), Error>

Ensures that at least a given number of local references can be created in the current thread.

pub fn register_native_methods<'other_local, T>( &mut self, class: T, methods: &[NativeMethod], ) -> Result<(), Error>
where T: Desc<'local, JClass<'other_local>>,

Bind function pointers to native methods of class according to method name and signature. For details see documentation.

pub fn unregister_native_methods<'other_local, T>( &mut self, class: T, ) -> Result<(), Error>
where T: Desc<'local, JClass<'other_local>>,

Unbind all native methods of class.

pub unsafe fn get_array_elements<'other_local, 'array, T>( &mut self, array: &'array JPrimitiveArray<'other_local, T>, mode: ReleaseMode, ) -> Result<AutoElements<'local, 'other_local, 'array, T>, Error>
where T: TypeArray,

Returns an [AutoElements] to access the elements of the given Java array.

The elements are accessible until the returned auto-release guard is dropped.

The returned array may be a copy of the Java array and changes made to the returned array will not necessarily be reflected in the original array until the [AutoElements] guard is dropped.

If you know in advance that you will only be reading from the array then pass [ReleaseMode::NoCopyBack] so that the JNI implementation knows that it’s not necessary to copy any data back to the original Java array when the [AutoElements] guard is dropped.

Since the returned array may be a copy of the Java array, changes made to the returned array will not necessarily be reflected in the original array until the corresponding Release*ArrayElements JNI method is called. [AutoElements] has a commit() method, to force a copy back of pending array changes if needed (and without releasing it).

§Safety
§No data races

This API has no built-in synchronization that ensures there won’t be any data races while accessing the array elements.

To avoid undefined behaviour it is the caller’s responsibility to ensure there will be no data races between other Rust or Java threads trying to access the same array.

Acquiring a [MonitorGuard] lock for the array could be one way of ensuring mutual exclusion between Rust and Java threads, so long as the Java threads also acquire the same lock via synchronized(array) {}.

§No aliasing

Callers must not create more than one [AutoElements] or [AutoElementsCritical] per Java array at the same time - even if there is no risk of a data race.

The reason for this restriction is that [AutoElements] and [AutoElementsCritical] implement DerefMut which can provide a mutable &mut [T] slice reference for the elements and it would constitute undefined behaviour to allow there to be more than one mutable reference that points to the same memory.

§jboolean elements

Keep in mind that arrays of jboolean values should only ever hold values of 0 or 1 because any other value could lead to undefined behaviour within the JVM.

Also see get_array_elements_critical which imposes additional restrictions that make it less likely to incur the cost of copying the array elements.

pub unsafe fn get_array_elements_critical<'other_local, 'array, 'env, T>( &'env mut self, array: &'array JPrimitiveArray<'other_local, T>, mode: ReleaseMode, ) -> Result<AutoElementsCritical<'local, 'other_local, 'array, 'env, T>, Error>
where T: TypeArray,

Returns an [AutoElementsCritical] to access the elements of the given Java array.

The elements are accessible during the critical section that exists until the returned auto-release guard is dropped.

This API imposes some strict restrictions that help the JNI implementation avoid any need to copy the underlying array elements before making them accessible to native code:

  1. No other use of JNI calls are allowed (on the same thread) within the critical section that exists while holding the [AutoElementsCritical] guard.
  2. No system calls can be made (Such as read) that may depend on a result from another Java thread.

The JNI spec does not specify what will happen if these rules aren’t adhered to but it should be assumed it will lead to undefined behaviour, likely deadlock and possible program termination.

Even with these restrictions the returned array may still be a copy of the Java array and changes made to the returned array will not necessarily be reflected in the original array until the [AutoElementsCritical] guard is dropped.

If you know in advance that you will only be reading from the array then pass [ReleaseMode::NoCopyBack] so that the JNI implementation knows that it’s not necessary to copy any data back to the original Java array when the [AutoElementsCritical] guard is dropped.

A nested scope or explicit use of std::mem::drop can be used to control when the returned [AutoElementsCritical] is dropped to minimize the length of the critical section.

If the given array is null, an Error::NullPtr is returned.

§Safety
§Critical Section Restrictions

Although this API takes a mutable reference to a [JNIEnv] which should ensure that it’s not possible to call JNI, this API is still marked as unsafe due to the complex, far-reaching nature of the critical-section restrictions imposed here that can’t be guaranteed simply through Rust’s borrow checker rules.

The rules above about JNI usage and system calls must be adhered to.

Using this API implies:

  1. All garbage collection will likely be paused during the critical section
  2. Any use of JNI in other threads may block if they need to allocate memory (due to the garbage collector being paused)
  3. Any use of system calls that will wait for a result from another Java thread could deadlock if that other thread is blocked by a paused garbage collector.

A failure to adhere to the critical section rules could lead to any undefined behaviour, including aborting the program.

§No data races

This API has no built-in synchronization that ensures there won’t be any data races while accessing the array elements.

To avoid undefined behaviour it is the caller’s responsibility to ensure there will be no data races between other Rust or Java threads trying to access the same array.

Acquiring a [MonitorGuard] lock for the array could be one way of ensuring mutual exclusion between Rust and Java threads, so long as the Java threads also acquire the same lock via synchronized(array) {}.

§No aliasing

Callers must not create more than one [AutoElements] or [AutoElementsCritical] per Java array at the same time - even if there is no risk of a data race.

The reason for this restriction is that [AutoElements] and [AutoElementsCritical] implement DerefMut which can provide a mutable &mut [T] slice reference for the elements and it would constitute undefined behaviour to allow there to be more than one mutable reference that points to the same memory.

§jboolean elements

Keep in mind that arrays of jboolean values should only ever hold values of 0 or 1 because any other value could lead to undefined behaviour within the JVM.

Also see get_array_elements which has fewer restrictions, but is is more likely to incur a cost from copying the array elements.

Trait Implementations§

source§

impl<'a> Deref for EnvParam<'a>

source§

type Target = JNIEnv<'a>

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl DerefMut for EnvParam<'_>

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.

Auto Trait Implementations§

§

impl<'a> Freeze for EnvParam<'a>

§

impl<'a> RefUnwindSafe for EnvParam<'a>

§

impl<'a> !Send for EnvParam<'a>

§

impl<'a> !Sync for EnvParam<'a>

§

impl<'a> Unpin for EnvParam<'a>

§

impl<'a> UnwindSafe for EnvParam<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

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

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T> IntoRequest<T> for T

source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<T> IntoResult<T> for T

§

type Err = Infallible

§

fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>

source§

impl<M> MetricVecRelabelExt for M

source§

fn relabel( self, metric_level: MetricLevel, relabel_threshold: MetricLevel, ) -> RelabeledMetricVec<M>

source§

fn relabel_n( self, metric_level: MetricLevel, relabel_threshold: MetricLevel, relabel_num: usize, ) -> RelabeledMetricVec<M>

source§

fn relabel_debug_1( self, relabel_threshold: MetricLevel, ) -> RelabeledMetricVec<M>

Equivalent to RelabeledMetricVec::with_metric_level_relabel_n with metric_level set to MetricLevel::Debug and relabel_num set to 1.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more