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}