1 use std::marker::PhantomData; 2 3 use crate::sys::jobject; 4 5 #[cfg(doc)] 6 use crate::{objects::GlobalRef, JNIEnv}; 7 8 /// Wrapper around [`sys::jobject`] that adds a lifetime to ensure that 9 /// the underlying JNI pointer won't be accessible to safe Rust code if the 10 /// object reference is released. 11 /// 12 /// It matches C's representation of the raw pointer, so it can be used in any 13 /// of the extern function argument positions that would take a `jobject`. 14 /// 15 /// Most other types in the `objects` module deref to this, as they do in the C 16 /// representation. 17 /// 18 /// The lifetime `'local` represents the local reference frame that this 19 /// reference belongs to. See the [`JNIEnv`] documentation for more information 20 /// about local reference frames. If `'local` is `'static`, then this reference 21 /// does not belong to a local reference frame, that is, it is either null or a 22 /// [global reference][GlobalRef]. 23 /// 24 /// Note that an *owned* `JObject` is always a local reference and will never 25 /// have the `'static` lifetime. [`GlobalRef`] does implement 26 /// <code>[AsRef]<JObject<'static>></code>, but this only yields a 27 /// *borrowed* `&JObject<'static>`, never an owned `JObject<'static>`. 28 /// 29 /// Local references belong to a single thread and are not safe to share across 30 /// threads. This type implements [`Send`] and [`Sync`] if and only if the 31 /// lifetime `'local` is `'static`. 32 #[repr(transparent)] 33 #[derive(Debug)] 34 pub struct JObject<'local> { 35 internal: jobject, 36 lifetime: PhantomData<&'local ()>, 37 } 38 39 unsafe impl Send for JObject<'static> {} 40 unsafe impl Sync for JObject<'static> {} 41 42 impl<'local> AsRef<JObject<'local>> for JObject<'local> { as_ref(&self) -> &JObject<'local>43 fn as_ref(&self) -> &JObject<'local> { 44 self 45 } 46 } 47 48 impl<'local> AsMut<JObject<'local>> for JObject<'local> { as_mut(&mut self) -> &mut JObject<'local>49 fn as_mut(&mut self) -> &mut JObject<'local> { 50 self 51 } 52 } 53 54 impl<'local> ::std::ops::Deref for JObject<'local> { 55 type Target = jobject; 56 deref(&self) -> &Self::Target57 fn deref(&self) -> &Self::Target { 58 &self.internal 59 } 60 } 61 62 impl<'local> JObject<'local> { 63 /// Creates a [`JObject`] that wraps the given `raw` [`jobject`] 64 /// 65 /// # Safety 66 /// 67 /// `raw` may be a null pointer. If `raw` is not a null pointer, then: 68 /// 69 /// * `raw` must be a valid raw JNI local reference. 70 /// * There must not be any other `JObject` representing the same local reference. 71 /// * The lifetime `'local` must not outlive the local reference frame that the local reference 72 /// was created in. from_raw(raw: jobject) -> Self73 pub unsafe fn from_raw(raw: jobject) -> Self { 74 Self { 75 internal: raw, 76 lifetime: PhantomData, 77 } 78 } 79 80 /// Returns the raw JNI pointer. as_raw(&self) -> jobject81 pub fn as_raw(&self) -> jobject { 82 self.internal 83 } 84 85 /// Unwrap to the internal jni type. into_raw(self) -> jobject86 pub fn into_raw(self) -> jobject { 87 self.internal 88 } 89 90 /// Creates a new null reference. 91 /// 92 /// Null references are always valid and do not belong to a local reference frame. Therefore, 93 /// the returned `JObject` always has the `'static` lifetime. null() -> JObject<'static>94 pub fn null() -> JObject<'static> { 95 unsafe { JObject::from_raw(std::ptr::null_mut() as jobject) } 96 } 97 } 98 99 impl<'local> std::default::Default for JObject<'local> { default() -> Self100 fn default() -> Self { 101 Self::null() 102 } 103 } 104