jni_glue/refs/
local.rs

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