Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
jni_mem.hpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Author: Petre Eftime <petre.p.eftime@intel.com>
7  * Copyright (c) 2016 Intel Corporation.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files (the
11  * "Software"), to deal in the Software without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 
29 #ifndef JAU_JNIMEM__HPP_
30 #define JAU_JNIMEM__HPP_
31 
32 #include <jni.h>
33 #include <stdexcept>
34 
35 #include <jau/basic_types.hpp>
36 
37 extern JavaVM* vm;
38 
39 
40 /*
41  * This class provides a lifetime-managed JNIEnv object, which attaches or
42  * detaches the current thread from the JVM automatically
43  */
45 private:
46  JNIEnv *env = nullptr;
47  bool needsDetach = false;
48 
49 public:
50  /* Attaches this thread to the JVM if it is not already attached */
52  /* Detaches this thread to the JVM if it is attached */
54 
55  /* Provides access to the local thread's JNIEnv object */
56  JNIEnv *operator*();
57  /* Provides access to the local thread's JNIEnv object's methods */
58  JNIEnv *operator->();
59 
60  /* Attaches this thread to the JVM if it is not already attached */
61  void attach();
62  /* Detaches this thread to the JVM if it is attached */
63  void detach();
64 };
65 
66 /* Each thread has a local jni_env variable of JNIEnvContainer type */
67 extern thread_local JNIEnvContainer jni_env;
68 
69 /*
70  * This class provides a lifetime-managed GlobalRef variable,
71  * which is automatically deleted when it goes out of scope.
72  *
73  * RAII-style acquire and relinquish via destructor
74  */
75 class JNIGlobalRef {
76 private:
77  jobject object;
78 
79 public:
80  static inline void check(jobject object, const char* file, int line) {
81  if( nullptr == object ) {
82  throw jau::RuntimeException("JNIGlobalRef::check: Null jobject", file, line);
83  }
84  }
85 
86  /* Creates a GlobalRef using a nullptr for API convenience, lazy assignment. */
87  JNIGlobalRef() noexcept;
88 
89  /* Creates a GlobalRef from an object passed to it */
90  JNIGlobalRef(jobject object);
91 
93  JNIGlobalRef(JNIGlobalRef &&o) noexcept;
94 
95  JNIGlobalRef& operator=(const JNIGlobalRef &o);
96  JNIGlobalRef& operator=(JNIGlobalRef &&o) noexcept;
97 
98  /* Deletes the stored GlobalRef */
99  ~JNIGlobalRef() noexcept;
100 
101  /** Clears the java reference, i.e. nulling it, without deleting the global reference via JNI. */
102  void clear() noexcept;
103 
104  /* Provides access to the stored GlobalRef as an jobject. */
105  jobject operator*() noexcept { return object; }
106 
107  /* Provides access to the stored GlobalRef as an jobject. */
108  jobject getObject() const noexcept { return object; }
109  /* Provides access to the stored GlobalRef as a jclass. */
110  jclass getClass() const noexcept { return (jclass)object; }
111 
112  bool operator==(const JNIGlobalRef& rhs) const noexcept;
113 
114  bool operator!=(const JNIGlobalRef& rhs) const noexcept
115  { return !( *this == rhs ); }
116 };
117 
118 /*
119  * This class provides a lifetime-managed 'PrimitiveArrayCritical' pinned heap,
120  * which is automatically released when it goes out of scope.
121  * <p>
122  * RAII-style acquire and relinquish via destructor
123  * </p>
124  */
125 template <typename T, typename U>
127 public:
128  enum Mode : jint {
129  /** Like default 0: If 'isCopy': Update the java array data with the copy and free the copy. */
131 
132  /** Like JNI_COMMIT: If 'isCopy': Update the java array data with the copy, but do not free the copy. */
133  UPDATE_NO_RELEASE = JNI_COMMIT,
134 
135  /** Like default JNI_ABORT: If 'isCopy': Do not update the java array data with the copy, but free the copy. */
137  };
138 
139 private:
140  JNIEnv *env;
141  Mode mode = UPDATE_AND_RELEASE;
142  U jarray = nullptr;
143  T* narray = nullptr;
144  jboolean isCopy = false;
145 
146 public:
147  JNICriticalArray(JNIEnv *env_val) : env(env_val) {}
148 
149  JNICriticalArray(const JNICriticalArray &o) = delete;
153 
154  /**
155  * Release the acquired primitive array, RAII style.
156  */
158  release();
159  }
160 
161  /**
162  * Manual release of the acquired primitive array,
163  * usually one likes to simply do this via the destructor, RAII style.
164  */
165  void release() {
166  if( nullptr != narray ) {
167  env->ReleasePrimitiveArrayCritical(jarray, narray, mode);
168  this->jarray = nullptr;
169  this->narray = nullptr;
170  this->env = nullptr;
171  }
172  }
173 
174  /**
175  * Acquired the primitive array.
176  */
177  T* get(U jarray_val, Mode mode_val=UPDATE_AND_RELEASE) {
178  if( nullptr == jarray_val ) {
179  return nullptr;
180  }
181  T* _narray = static_cast<T*>( env->GetPrimitiveArrayCritical(jarray_val, &isCopy) );
182  if( nullptr != _narray ) {
183  this->mode = mode_val;
184  this->jarray = jarray_val;
185  this->narray = _narray;
186  return _narray;
187  }
188  return nullptr;
189  }
190 
191  /**
192  * Returns true if the primitive array had been acquired
193  * and the JVM utilizes a copy of the underlying java array.
194  */
195  bool getIsCopy() const { return isCopy; }
196 };
197 
198 #endif /* JAU_JNIMEM__HPP_ */
199 
JNIGlobalRef::clear
void clear() noexcept
Clears the java reference, i.e.
JNICriticalArray::release
void release()
Manual release of the acquired primitive array, usually one likes to simply do this via the destructo...
Definition: jni_mem.hpp:165
JNIEnvContainer::operator->
JNIEnv * operator->()
JNIEnvContainer::operator*
JNIEnv * operator*()
JNIGlobalRef::getObject
jobject getObject() const noexcept
Definition: jni_mem.hpp:108
JNICriticalArray::JNICriticalArray
JNICriticalArray(JNIEnv *env_val)
Definition: jni_mem.hpp:147
JNIGlobalRef
Definition: jni_mem.hpp:75
JNIEnvContainer::detach
void detach()
JNICriticalArray::getIsCopy
bool getIsCopy() const
Returns true if the primitive array had been acquired and the JVM utilizes a copy of the underlying j...
Definition: jni_mem.hpp:195
JNICriticalArray::JNICriticalArray
JNICriticalArray(JNICriticalArray &&o)=delete
jni_env
thread_local JNIEnvContainer jni_env
JNIEnvContainer
Definition: jni_mem.hpp:44
JNICriticalArray::UPDATE_AND_RELEASE
@ UPDATE_AND_RELEASE
Like default 0: If 'isCopy': Update the java array data with the copy and free the copy.
Definition: jni_mem.hpp:130
JNICriticalArray::~JNICriticalArray
~JNICriticalArray()
Release the acquired primitive array, RAII style.
Definition: jni_mem.hpp:157
JNIGlobalRef::operator==
bool operator==(const JNIGlobalRef &rhs) const noexcept
JNIGlobalRef::check
static void check(jobject object, const char *file, int line)
Definition: jni_mem.hpp:80
JNICriticalArray::Mode
Mode
Definition: jni_mem.hpp:128
JNIGlobalRef::operator!=
bool operator!=(const JNIGlobalRef &rhs) const noexcept
Definition: jni_mem.hpp:114
JNIEnvContainer::JNIEnvContainer
JNIEnvContainer()
jau::RuntimeException
Definition: basic_types.hpp:66
JNICriticalArray::get
T * get(U jarray_val, Mode mode_val=UPDATE_AND_RELEASE)
Acquired the primitive array.
Definition: jni_mem.hpp:177
JNIEnvContainer::~JNIEnvContainer
~JNIEnvContainer()
JNICriticalArray
Definition: jni_mem.hpp:126
JNIEnvContainer::attach
void attach()
JNIGlobalRef::JNIGlobalRef
JNIGlobalRef() noexcept
JNICriticalArray::NO_UPDATE_AND_RELEASE
@ NO_UPDATE_AND_RELEASE
Like default JNI_ABORT: If 'isCopy': Do not update the java array data with the copy,...
Definition: jni_mem.hpp:136
JNICriticalArray::operator=
JNICriticalArray & operator=(JNICriticalArray &&o)=delete
JNICriticalArray::JNICriticalArray
JNICriticalArray(const JNICriticalArray &o)=delete
basic_types.hpp
vm
JavaVM * vm
JNICriticalArray::UPDATE_NO_RELEASE
@ UPDATE_NO_RELEASE
Like JNI_COMMIT: If 'isCopy': Update the java array data with the copy, but do not free the copy.
Definition: jni_mem.hpp:133
JNICriticalArray::operator=
JNICriticalArray & operator=(const JNICriticalArray &o)=delete
JNIGlobalRef::getClass
jclass getClass() const noexcept
Definition: jni_mem.hpp:110