java_spaghetti/refs/
global.rs

1use std::marker::PhantomData;
2
3use jni_sys::*;
4
5use crate::{Env, Local, Ref, ReferenceType, VM};
6
7/// A [Global](https://www.ibm.com/support/knowledgecenter/en/SSYKE2_8.0.0/com.ibm.java.vm.80.doc/docs/jni_refs.html),
8/// non-null, reference to a Java object (+ [VM]).
9///
10/// Unlike Local, this can be stored statically and shared between threads.  This has a few caveats:
11/// * You must create a [Ref] before use.
12/// * The [Global] can be invalidated if the [VM] is unloaded.
13///
14/// **Not FFI Safe:**  #\[repr(rust)\], and exact layout is likely to change - depending on exact features used - in the
15/// future.  Specifically, on Android, since we're guaranteed to only have a single ambient [VM], we can likely store the
16/// *const JavaVM in static and/or thread local storage instead of lugging it around in every [Local].  Of course, there's
17/// no guarantee that's actually an *optimization*...
18pub struct Global<T: ReferenceType> {
19    object: jobject,
20    vm: VM,
21    pd: PhantomData<T>,
22}
23
24unsafe impl<T: ReferenceType> Send for Global<T> {}
25unsafe impl<T: ReferenceType> Sync for Global<T> {}
26
27impl<T: ReferenceType> Global<T> {
28    pub unsafe fn from_raw(vm: VM, object: jobject) -> Self {
29        Self {
30            object,
31            vm,
32            pd: PhantomData,
33        }
34    }
35
36    pub fn vm(&self) -> VM {
37        self.vm
38    }
39
40    pub fn as_raw(&self) -> jobject {
41        self.object
42    }
43
44    pub fn into_raw(self) -> jobject {
45        let object = self.object;
46        std::mem::forget(self); // Don't delete the object.
47        object
48    }
49
50    pub fn as_local<'env>(&self, env: Env<'env>) -> Local<'env, T> {
51        let jnienv = env.as_raw();
52        let object = unsafe { ((**jnienv).v1_2.NewLocalRef)(jnienv, self.as_raw()) };
53        unsafe { Local::from_raw(env, object) }
54    }
55
56    pub fn as_ref<'env>(&'env self, env: Env<'env>) -> Ref<'env, T> {
57        unsafe { Ref::from_raw(env, self.object) }
58    }
59}
60
61impl<'env, T: ReferenceType> From<Local<'env, T>> for Global<T> {
62    fn from(x: Local<'env, T>) -> Self {
63        x.as_global()
64    }
65}
66
67impl<'env, T: ReferenceType> From<Ref<'env, T>> for Global<T> {
68    fn from(x: Ref<'env, T>) -> Self {
69        x.as_global()
70    }
71}
72
73impl<'env, T: ReferenceType> From<&Local<'env, T>> for Global<T> {
74    fn from(x: &Local<'env, T>) -> Self {
75        x.as_global()
76    }
77}
78
79impl<'env, T: ReferenceType> From<&Ref<'env, T>> for Global<T> {
80    fn from(x: &Ref<'env, T>) -> Self {
81        x.as_global()
82    }
83}
84
85impl<T: ReferenceType> Clone for Global<T> {
86    fn clone(&self) -> Self {
87        self.vm.with_env(|env| {
88            let env = env.as_raw();
89            let object = unsafe { ((**env).v1_2.NewGlobalRef)(env, self.object) };
90            Self {
91                object,
92                vm: self.vm,
93                pd: PhantomData,
94            }
95        })
96    }
97}
98
99impl<T: ReferenceType> Drop for Global<T> {
100    fn drop(&mut self) {
101        self.vm.with_env(|env| {
102            let env = env.as_raw();
103            unsafe { ((**env).v1_2.DeleteGlobalRef)(env, self.object) }
104        });
105    }
106}