Struct java_spaghetti::Env
source · pub struct Env<'env> { /* private fields */ }
Expand description
FFI: Use Env instead of *const JNIEnv. This represents a per-thread Java exection environment.
A “safe” alternative to jni_sys::JNIEnv raw pointers, with the following caveats:
-
A null env will result in undefined behavior. Java should not be invoking your native functions with a null *mut JNIEnv, however, so I don’t believe this is a problem in practice unless you’ve bindgened the C header definitions elsewhere, calling them (requiring
unsafe
), and passing null pointers (generally UB for JNI functions anyways, so can be seen as a caller soundness issue.) -
Allowing the underlying JNIEnv to be modified is undefined behavior. I don’t believe the JNI libraries modify the JNIEnv, so as long as you’re not accepting a *mut JNIEnv elsewhere, using unsafe to dereference it, and mucking with the methods on it yourself, I believe this “should” be fine.
§Example
§MainActivity.java
package com.maulingmonkey.example;
public class MainActivity extends androidx.appcompat.app.AppCompatActivity {
@Override
public native boolean dispatchKeyEvent(android.view.KeyEvent keyEvent);
// ...
}
§main_activity.rs
use jni_sys::{jboolean, jobject, JNI_TRUE}; // TODO: Replace with safer equivalent
use java_spaghetti::Env;
#[no_mangle] pub extern "system"
fn Java_com_maulingmonkey_example_MainActivity_dispatchKeyEvent<'env>(
_env: Env<'env>,
_this: jobject, // TODO: Replace with safer equivalent
_key_event: jobject // TODO: Replace with safer equivalent
) -> jboolean {
// ...
JNI_TRUE
}
Implementations§
source§impl<'env> Env<'env>
impl<'env> Env<'env>
pub unsafe fn from_raw(ptr: *mut JNIEnv) -> Self
pub fn as_raw(&self) -> *mut JNIEnv
pub fn vm(&self) -> VM
pub unsafe fn new_string(self, chars: *const jchar, len: jsize) -> jstring
pub unsafe fn get_string_length(self, string: jstring) -> jsize
pub unsafe fn get_string_chars(self, string: jstring) -> *const jchar
pub unsafe fn release_string_chars(self, string: jstring, chars: *const jchar)
sourcepub unsafe fn set_class_loader(classloader: jobject)
pub unsafe fn set_class_loader(classloader: jobject)
Set a custom class loader to use instead of JNI FindClass
calls.
When calling Java methods, java-spaghetti
may need to resolve class names (as strings)
into jclass
pointers. The JNI API provides FindClass
to do it. However, it is
hardcoded to use the class loader for the class that called the currently-running native method.
This works fine most of the time, except:
- On a thread created by native code (such as with
std::thread::spawn()
), there is no “class that called a native method” in the call stack, since the execution already started in native code. In this case,FindClass
falls back to the system class loader. - On Android, the system class loader can’t find classes for your application, it can only find classes from the Android frameworks.
set_class_loader
allows you to set a ClassLoader
instance that java-spaghetti
will use to
resolve class names, by calling the loadClass
method, instead of doing JNI FindClass
calls.
Calling this with a null classloader
reverts back to using JNI FindClass
.
§Safety
classloader
must be a global reference to ajava.lang.ClassLoader
instance.- The library does not take ownership of the global reference. I.e. it will not delete it if you
call
set_class_loader
with another class loader, or with null.