1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use super::*; /// A [Local](https://www.ibm.com/support/knowledgecenter/en/SSYKE2_8.0.0/com.ibm.java.vm.80.doc/docs/jni_refs.html), /// non-null, reference to a Java object (+ &[Env]) limited to the current thread/stack. /// /// Including the env allows for the convenient execution of methods without having to individually pass the env as an /// argument to each and every one. Since this is limited to the current thread/stack, these cannot be sanely stored /// in any kind of static storage, nor shared between threads - instead use a [Global] if you need to do either. /// /// Will DeleteLocalRef when dropped, invalidating the jobject but ensuring threads that rarely or never return to /// Java may run without being guaranteed to eventually exhaust their local reference limit. If this is not desired, /// convert to a plain Ref with: /// /// ```rust,no_run /// # use jni_glue::*; /// # fn example<Class: AsValidJObjectAndEnv>(local: Local<Class>) { /// let local = Local::leak(local); /// # } /// ``` /// /// **Not FFI Safe:** #\[repr(rust)\], and exact layout is likely to change - depending on exact features used - in the /// future. Specifically, on Android, since we're guaranteed to only have a single ambient VM, we can likely store the /// \*const JNIEnv in thread local storage instead of lugging it around in every Local. Of course, there's no /// guarantee that's actually an *optimization*... /// /// [Env]: struct.Env.html /// [Global]: struct.Global.html pub struct Local<'env, Class: AsValidJObjectAndEnv> { pub(crate) oae: ObjectAndEnv, pub(crate) _env: PhantomData<&'env Env>, pub(crate) _class: PhantomData<&'env Class>, } // Could implement clone if necessary via NewLocalRef // Do *not* implement Copy, cannot be safely done. impl<'env, Class: AsValidJObjectAndEnv> Local<'env, Class> { pub unsafe fn from_env_object(env: *const JNIEnv, object: jobject) -> Self { Self { oae: ObjectAndEnv { object, env }, _env: PhantomData, _class: PhantomData, } } pub fn leak(local: Self) -> Ref<'env, Class> { let result = Ref { oae: ObjectAndEnv { object: local.oae.object, env: local.oae.env, }, _env: PhantomData, _class: PhantomData, }; std::mem::forget(local); // Don't allow local to DeleteLocalRef the jobject result } } impl<'env, Class: AsValidJObjectAndEnv> Deref for Local<'env, Class> { type Target = Class; fn deref(&self) -> &Self::Target { unsafe { &*(&self.oae as *const ObjectAndEnv as *const Self::Target) } } } impl<'env, Class: AsValidJObjectAndEnv> Drop for Local<'env, Class> { fn drop(&mut self) { let env = self.oae.env as *mut JNIEnv; unsafe { (**env).DeleteLocalRef.unwrap()(env, self.oae.object); } } }