The global variable's type does not implement Sync
, so the normal solutions to global variables do not work. Said type is JNIEnv
from the jni
crate.
I am aware that having a not up-to-date copy of a JNI environment could lead to broken behavior in many cases, but I am only accessing one class that is guaranteed to never change, only ever calling functions within it, meaning it should be safe to have a reference to it.
The reasoning behind needing a global copy of the JNI environment is because I need a Lua VM from the mlua
crate to be able to call functions within Java, critically, without being able to access the JNI environment, as the Lua code being run is user-specified, meaning that would be a massive security hole. I cannot sandbox the Lua code if it has access to the JNI environment.
If someone could think of a better way of doing this, I would be grateful, as I really don't like this solution. But I cannot think of any other way this could be accomplished.
Here's the code that I'm talking about (link):
// [...]
static mut JNI_ENV: Option<JNIEnv> = Option::None;
// Function for Lua to call to draw a pixel on the screen
unsafe fn draw_pix(x: u32, y: u32)
{
let dllhandler: JClass;
match JNI_ENV.expect("JNI_ENV is None").find_class("bluefire_06/mimosa_computers/lua/DLLHandler") {
Ok(class) => dllhandler = class,
Err(e) => {println!("{}", e.to_string()); dllhandler = JClass::default()}
}
let args: [JValue; 2] = [JValue::Int(x.try_into().expect("X value is out of range")), JValue::Int(y.try_into().expect("Y value is out of range"))];
match JNI_ENV.expect("JNI_ENV is None").call_static_method(dllhandler, "drawPix", "(II)V", &args) {
Ok(_) => (),
Err(e) => println!("{}", e.to_string())
}
}
// [...]
#[no_mangle]
pub extern "system" fn Java_bluefire_106_mimosa_1computers_lua_DLLHandler_initLuaDLL(env: JNIEnv, _class: JClass)
{
// I know this isn't valid
let envCopy = env.clone();
unsafe {
JNI_ENV = Some(envCopy);
}
// [...]
}
// [...]
Also, I know this can't be run in the playground, but that's basically impossible to do even if I included any more code, as you can't create a JNIEnv without actually getting Java code to run the native code.