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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::{convert::From, sync::Arc};
use log::{debug, warn};
use crate::{errors::Result, objects::JObject, sys, JNIEnv, JavaVM};
#[derive(Clone)]
pub struct GlobalRef {
inner: Arc<GlobalRefGuard>,
}
struct GlobalRefGuard {
obj: JObject<'static>,
vm: JavaVM,
}
unsafe impl Send for GlobalRef {}
unsafe impl Sync for GlobalRef {}
impl<'a> From<&'a GlobalRef> for JObject<'a> {
fn from(other: &'a GlobalRef) -> JObject<'a> {
other.as_obj()
}
}
impl GlobalRef {
pub(crate) unsafe fn from_raw(vm: JavaVM, raw_global_ref: sys::jobject) -> Self {
GlobalRef {
inner: Arc::new(GlobalRefGuard::from_raw(vm, raw_global_ref)),
}
}
pub fn as_obj(&self) -> JObject {
self.inner.as_obj()
}
}
impl GlobalRefGuard {
unsafe fn from_raw(vm: JavaVM, obj: sys::jobject) -> Self {
GlobalRefGuard {
obj: JObject::from(obj),
vm,
}
}
pub fn as_obj(&self) -> JObject {
self.obj
}
}
impl Drop for GlobalRefGuard {
fn drop(&mut self) {
fn drop_impl(env: &JNIEnv, global_ref: JObject) -> Result<()> {
let internal = env.get_native_interface();
jni_unchecked!(internal, DeleteGlobalRef, global_ref.into_inner());
Ok(())
}
let res = match self.vm.get_env() {
Ok(env) => drop_impl(&env, self.as_obj()),
Err(_) => {
warn!("Dropping a GlobalRef in a detached thread. Fix your code if this message appears frequently (see the GlobalRef docs).");
self.vm
.attach_current_thread()
.and_then(|env| drop_impl(&env, self.as_obj()))
}
};
if let Err(err) = res {
debug!("error dropping global ref: {:#?}", err);
}
}
}