jni_glue/refs/global.rs
1use super::*;
2
3
4
5/// A [Global](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 (+ &[VM]).
7///
8/// Unlike Local, this can be stored statically and shared between threads. This has a few caveats:
9/// * You must create a [GlobalRef] before use.
10/// * The [Global] can be invalidated if the [VM] is unloaded.
11///
12/// **Not FFI Safe:** #\[repr(rust)\], and exact layout is likely to change - depending on exact features used - in the
13/// future. Specifically, on Android, since we're guaranteed to only have a single ambient [VM], we can likely store the
14/// *const JavaVM in static and/or thread local storage instead of lugging it around in every [Local]. Of course, there's
15/// no guarantee that's actually an *optimization*...
16///
17/// [VM]: struct.VM.html
18/// [Global]: struct.Global.html
19/// [GlobalRef]: type.GlobalRef.html
20pub struct Global<Class: AsValidJObjectAndEnv> {
21 pub(crate) global: jobject,
22 pub(crate) gen_vm: GenVM,
23 pub(crate) pd: PhantomData<Class>,
24}
25
26unsafe impl<Class: AsValidJObjectAndEnv> Send for Global<Class> {}
27unsafe impl<Class: AsValidJObjectAndEnv> Sync for Global<Class> {}
28
29impl<Class: AsValidJObjectAndEnv> Global<Class> {
30 pub fn with<'env>(&'env self, env: &'env Env) -> GlobalRef<'env, Class> {
31 assert_eq!(self.gen_vm, env.get_gen_vm()); // Soundness check - env *must* belong to the same VM!
32 unsafe { self.with_unchecked(env) }
33 }
34
35 pub unsafe fn with_unchecked<'env>(&'env self, env: &'env Env) -> GlobalRef<'env, Class> {
36 let env = env.as_jni_env();
37 GlobalRef {
38 oae: ObjectAndEnv {
39 object: self.global,
40 env,
41 },
42 _env: PhantomData,
43 _class: PhantomData,
44 }
45 }
46}
47
48impl<'env, Class: AsValidJObjectAndEnv> From<Local<'env, Class>> for Global<Class> {
49 fn from(local: Local<'env, Class>) -> Global<Class> {
50 let env = unsafe { Env::from_ptr(local.oae.env) };
51 let jnienv = env.as_jni_env();
52 let gen_vm = env.get_gen_vm();
53 let global = unsafe { (**jnienv).NewGlobalRef.unwrap()(jnienv, local.oae.object) };
54 Global {
55 global,
56 gen_vm,
57 pd: PhantomData,
58 }
59 }
60}
61
62impl<Class: AsValidJObjectAndEnv> Drop for Global<Class> {
63 fn drop(&mut self) {
64 VMS.read().unwrap().use_vm(self.gen_vm, |vm|{
65 vm.with_env(|env|{
66 let env = env.as_jni_env();
67 unsafe { (**env).DeleteGlobalRef.unwrap()(env, self.global); }
68 });
69 });
70 }
71}
72
73
74
75/// A [Global](https://www.ibm.com/support/knowledgecenter/en/SSYKE2_8.0.0/com.ibm.java.vm.80.doc/docs/jni_refs.html),
76/// non-null, reference to a Java object (+ &Env).
77///
78/// Much like Local, the inclusion of an Env means this cannot be stored statically or shared between threads.
79///
80/// **Not FFI Safe:** #\[repr(rust)\], and exact layout is likely to change - depending on exact features used - in the
81/// future. Specifically, on Android, since we're guaranteed to only have a single ambient VM, we can likely store the
82/// \*const JNIEnv in thread local storage instead of lugging it around in every Local. Of course, there's no
83/// guarantee that's actually an *optimization*...
84pub type GlobalRef<'env, Class> = Ref<'env, Class>;