Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
helper_jni.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020, 2022 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef JAU_HELPER_JNI_HPP_
27#define JAU_HELPER_JNI_HPP_
28
29#include <limits>
30#include <vector>
31#include <memory>
32#include <jni.h>
33
34#include <jau/java_uplink.hpp>
35#include <jau/basic_algos.hpp>
36#include <jau/basic_types.hpp>
37#include <jau/darray.hpp>
38#include <jau/io_util.hpp>
39#include <jau/functional.hpp>
40
41#include <jau/jni/jni_mem.hpp>
42
43namespace jau::jni {
44
45 /** \addtogroup JavaVM
46 *
47 * @{
48 */
49
50 //
51 // C++ <-> java exceptions
52 //
53
54 /**
55 * Return true if a java exception occurred, otherwise false.
56 * <p>
57 * In case of an exception, the information might be logged to stderr.
58 * </p>
59 * <p>
60 * In case of an exception, user shall release resourced in their JNI code
61 * and leave immediately.
62 * </p>
63 */
64 bool java_exception_check(JNIEnv *env, const char* file, int line);
65
66 /**
67 * Throws a C++ exception if a java exception occurred, otherwise do nothing.
68 * <p>
69 * In case of an exception, the information might be logged to stderr.
70 * </p>
71 * <p>
72 * In case of an exception and hence thrown C++ exception,
73 * might want to catch all and handle it via {@link #rethrow_and_raise_java_exception(JNIEnv*)}.
74 * </p>
75 */
76 void java_exception_check_and_throw(JNIEnv *env, const char* file, int line);
77
78 void print_native_caught_exception_fwd2java(const jau::OutOfMemoryError &e, const char* file, int line);
79 void print_native_caught_exception_fwd2java(const jau::RuntimeException &e, const char* file, int line);
80 void print_native_caught_exception_fwd2java(const std::exception &e, const char* file, int line);
81 void print_native_caught_exception_fwd2java(const std::string &msg, const char* file, int line);
82 void print_native_caught_exception_fwd2java(const char * cmsg, const char* file, int line);
83
84 void raise_java_exception(JNIEnv *env, const std::exception &e, const char* file, int line);
85 void raise_java_exception(JNIEnv *env, const std::runtime_error &e, const char* file, int line);
86 void raise_java_exception(JNIEnv *env, const jau::RuntimeException &e, const char* file, int line);
87 void raise_java_exception(JNIEnv *env, const jau::InternalError &e, const char* file, int line);
88 void raise_java_exception(JNIEnv *env, const jau::NullPointerException &e, const char* file, int line);
89 void raise_java_exception(JNIEnv *env, const jau::IllegalArgumentException &e, const char* file, int line);
90 void raise_java_exception(JNIEnv *env, const std::invalid_argument &e, const char* file, int line);
91 void raise_java_exception(JNIEnv *env, const jau::IllegalStateException &e, const char* file, int line);
92 void raise_java_exception(JNIEnv *env, const jau::UnsupportedOperationException &e, const char* file, int line);
93 void raise_java_exception(JNIEnv *env, const jau::IndexOutOfBoundsException &e, const char* file, int line);
94 void raise_java_exception(JNIEnv *env, const std::bad_alloc &e, const char* file, int line);
95 void raise_java_exception(JNIEnv *env, const jau::OutOfMemoryError &e, const char* file, int line);
96
97 /**
98 * Re-throw current exception and raise respective java exception
99 * using any matching function above.
100 */
101 void rethrow_and_raise_java_exception_jauimpl(JNIEnv *env, const char* file, int line);
102
103 /**
104 * Re-throw current exception and raise respective java exception
105 * using any matching function above.
106 */
107 #define rethrow_and_raise_java_exception_jau(E) jau::jni::rethrow_and_raise_java_exception_jauimpl((E), __FILE__, __LINE__)
108 // inline void rethrow_and_raise_java_exception_jau(JNIEnv *env) { rethrow_and_raise_java_exception_jauimpl(env, __FILE__, __LINE__); }
109
110 //
111 // Basic
112 //
113
114 jfieldID getField(JNIEnv *env, jobject obj, const char* field_name, const char* field_signature);
115 inline jfieldID getInstanceField(JNIEnv *env, jobject obj) {
116 return getField(env, obj, "nativeInstance", "J");
117 }
118 jobject getObjectFieldValue(JNIEnv *env, jobject obj, const char* field_name, const char* field_signature);
119 std::string getStringFieldValue(JNIEnv *env, jobject obj, const char* field_name);
120 jlong getLongFieldValue(JNIEnv *env, jobject obj, const char* field_name);
121 jint getIntFieldValue(JNIEnv *env, jobject obj, const char* field_name);
122
123 jclass search_class(JNIEnv *env, const char *clazz_name);
124 jclass search_class(JNIEnv *env, jobject obj);
125 jclass search_class(JNIEnv *env, JavaUplink &object);
126
127 jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name,
128 const char *prototype, bool is_static);
129 jfieldID search_field(JNIEnv *env, jclass clazz, const char *field_name,
130 const char *type, bool is_static);
131
132 bool from_jboolean_to_bool(const jboolean val);
133
134 std::string from_jstring_to_string(JNIEnv *env, jstring str);
135 jstring from_string_to_jstring(JNIEnv *env, const std::string & str);
136
137 jau::io::secure_string from_jbytebuffer_to_sstring(JNIEnv *env, jobject jbytebuffer);
138
139 jobject get_new_arraylist(JNIEnv *env, jsize size, jmethodID *add);
140
141 jobject convert_vector_bytes_to_jarraylist(JNIEnv *env, const std::vector<std::vector<uint8_t>>& array);
142 jobject convert_vector_string_to_jarraylist(JNIEnv *env, const std::vector<std::string>& array);
143 jobject convert_vector_stringview_to_jarraylist(JNIEnv *env, const std::vector<std::string_view>& array);
144 std::vector<std::string> convert_jlist_string_to_vector(JNIEnv *env, jobject jlist);
145
146 template< class byte_container_type,
147 std::enable_if_t<std::is_integral_v<typename byte_container_type::value_type> &&
148 std::is_convertible_v<typename byte_container_type::value_type, jbyte>,
149 bool> = true>
150 jbyteArray convert_bytes_to_jbytearray(JNIEnv *env, const byte_container_type& data) {
151 const size_t data_size = data.size();
152 jbyteArray jdata = env->NewByteArray((jsize)data_size);
153 env->SetByteArrayRegion(jdata, 0, (jsize)data_size, (const jbyte *)data.data());
155 return jdata;
156 }
157
158 //
159 // C++ JavaAnon implementation
160 //
161
162 /**
163 * Implementation for JavaAnon,
164 * by simply wrapping a JNIGlobalRef instance.
165 */
166 class JavaGlobalObj : public JavaAnon {
167 private:
168 JNIGlobalRef javaObjectRef;
169 jmethodID mNotifyDeleted;
170
171 public:
172 static inline void check(const JavaAnonRef& shref, const char* file, int line) {
173 if( nullptr == shref ) {
174 throw RuntimeException("JavaGlobalObj::check: Null shared-JavaAnonObj", file, line);
175 }
176 if( 0 == shref.use_count() ) { // safe-guard for concurrent dtor
177 throw RuntimeException("JavaGlobalObj::check: Empty shared-JavaAnonObj", file, line);
178 }
179 const jobject obj = static_cast<const JavaGlobalObj*>(shref.get())->getObject();
180 if( nullptr == obj ) {
181 throw RuntimeException("JavaGlobalObj::check: Null object", file, line);
182 }
183 }
184 static inline jobject checkAndGetObject(const JavaAnonRef& shref, const char* file, int line) {
185 if( nullptr == shref ) {
186 throw RuntimeException("JavaGlobalObj::check: Null shared-JavaAnonObj", file, line);
187 }
188 if( 0 == shref.use_count() ) { // safe-guard for concurrent dtor
189 throw RuntimeException("JavaGlobalObj::check: Empty shared-JavaAnonObj", file, line);
190 }
191 const jobject obj = static_cast<const JavaGlobalObj*>(shref.get())->getObject();
192 if( nullptr == obj ) {
193 throw RuntimeException("JavaGlobalObj::check: Null object", file, line);
194 }
195 return obj;
196 }
197 static bool isValid(const JavaAnonRef& shref) noexcept {
198 if( nullptr == shref || 0 == shref.use_count() ) {
199 return false;
200 }
201 const jobject obj = static_cast<const JavaGlobalObj*>(shref.get())->getObject();
202 if( nullptr == obj ) {
203 return false;
204 }
205 return true;
206 }
207 JavaGlobalObj(jobject obj, jmethodID mNotifyDeleted_) noexcept
208 : javaObjectRef(obj), mNotifyDeleted(mNotifyDeleted_) { }
209
210 JavaGlobalObj(const JNIGlobalRef& obj, jmethodID mNotifyDeleted_) noexcept
211 : javaObjectRef(obj), mNotifyDeleted(mNotifyDeleted_) { }
212
213 JavaGlobalObj(JNIGlobalRef && obj, jmethodID mNotifyDeleted_) noexcept
214 : javaObjectRef(std::move(obj)), mNotifyDeleted(mNotifyDeleted_) { }
215
216 JavaGlobalObj(const JavaGlobalObj &o) noexcept = default;
217 JavaGlobalObj(JavaGlobalObj &&o) noexcept = default;
218 JavaGlobalObj& operator=(const JavaGlobalObj &o) noexcept = default;
219 JavaGlobalObj& operator=(JavaGlobalObj &&o) noexcept = default;
220
221 ~JavaGlobalObj() noexcept override;
222
223 std::string toString() const noexcept override {
224 const uint64_t ref = (uint64_t)(void*)javaObjectRef.getObject();
225 return "JavaGlobalObj["+to_hexstring(ref)+"]";
226 }
227
228 const JNIGlobalRef & getJavaObject() const noexcept { return javaObjectRef; }
229 JNIGlobalRef getJavaObject() noexcept { return javaObjectRef; }
230
231 /* Provides access to the stored GlobalRef as an jobject. */
232 jobject getObject() const noexcept { return javaObjectRef.getObject(); }
233 /* Provides access to the stored GlobalRef as a jclass. */
234 jclass getClass() const noexcept { return javaObjectRef.getClass(); }
235
236 /* Provides access to the stored GlobalRef as an getJavaObject. */
237 static JNIGlobalRef GetJavaObject(const JavaAnonRef & shref) noexcept {
238 return static_cast<JavaGlobalObj*>(shref.get())->getJavaObject();
239 }
240 /* Provides access to the stored GlobalRef as an jobject. */
241 static jobject GetObject(const JavaAnonRef & shref) noexcept {
242 return static_cast<JavaGlobalObj*>(shref.get())->getObject();
243 }
244
245 /* Provides access to the stored GlobalRef as a jclass. */
246 static jclass GetClass(const JavaAnonRef & shref) noexcept {
247 return static_cast<JavaGlobalObj*>(shref.get())->getClass();
248 }
249 };
250 typedef std::shared_ptr<JavaGlobalObj> JavaGlobalObjRef;
251
252 //
253 // C++ JavaAnon <-> java access, all generic
254 //
255 // We prefer using `std::shared_ptr<T>` instead of a `naked pointer`,
256 // this way we automatically preserve the native instance lifecycle while within a JNI method.
257 //
258
259 template <typename T>
260 T *getObjectRef(JNIEnv *env, jobject obj, const char* field_name)
261 {
262 jlong jobj = env->GetLongField(obj, getField(env, obj, field_name, "J"));
264 return reinterpret_cast<T *>(jobj);
265 }
266
267 template <typename T>
268 void setObjectRef(JNIEnv *env, jobject obj, T *t, const char* field_name)
269 {
270 jlong jobj = reinterpret_cast<jlong>(t);
271 env->SetLongField(obj, getField(env, obj, field_name, "J"), jobj);
273 }
274
275 /**
276 * Returns the cast `shared_ptr<T>` pointer from the java object's `long nativeInstance` field.
277 *
278 * If `throw_on_nullptr` is true, throws an exception if the shared_ptr<T> pointer is nullptr.
279 *
280 * @tparam T
281 * @param instance
282 * @param throw_on_nullptr
283 * @return
284 */
285 template <typename T>
286 std::shared_ptr<T> * castInstance(jlong instance, const bool throw_on_nullptr=true)
287 {
288 std::shared_ptr<T> * ref_ptr = reinterpret_cast<std::shared_ptr<T> *>(instance);
289 if( throw_on_nullptr ) {
290 if (nullptr == ref_ptr) {
291 throw jau::RuntimeException("null reference store", E_FILE_LINE);
292 }
293 }
294 return ref_ptr;
295 }
296
297 /**
298 * Returns the cast `shared_ptr<T>` pointer from the java object's `long nativeInstance` field.
299 *
300 * If `throw_on_nullptr` is true, throws an exception if either the shared_ptr<T> pointer or
301 * its managed object reference is nullptr.
302 *
303 * @tparam T
304 * @param env
305 * @param obj
306 * @param throw_on_nullptr if true, throws exception if instance reference is nullptr (default). Otherwise not.
307 */
308 template <typename T>
309 std::shared_ptr<T>* getInstance(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true) {
310 const jlong nativeInstance = env->GetLongField(obj, getInstanceField(env, obj));
312 std::shared_ptr<T>* ref_ptr = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
313 if( throw_on_nullptr ) {
314 if (nullptr == ref_ptr) {
315 throw jau::RuntimeException("null reference store", E_FILE_LINE);
316 }
317 if (nullptr == *ref_ptr) {
318 throw jau::RuntimeException("null reference", E_FILE_LINE);
319 }
320 }
321 return ref_ptr;
322 }
323
324 /**
325 * Deletes the `std::shared_ptr<T>` storage of the java object if exists first
326 * and writes the given `std::shared_ptr<T>` storage pointer into its `long nativeInstance` field.
327 *
328 * @tparam T
329 * @param env
330 * @param obj
331 * @param t
332 */
333 template <typename T>
334 void setInstance(JNIEnv *env, jobject obj, const std::shared_ptr<T>& t)
335 {
336 if (t == nullptr) {
337 throw jau::RuntimeException("Trying to create null object", E_FILE_LINE);
338 }
339 const jlong instance = (jlong) (intptr_t) &t;
340
341 jfieldID instance_field = getInstanceField(env, obj);
343 {
344 const jlong nativeInstance = env->GetLongField(obj, instance_field);
346 std::shared_ptr<T>* other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
347 if( nullptr != other ) {
348 delete other;
349 }
350 }
351 env->SetLongField(obj, instance_field, instance);
353 }
354
355
356 /**
357 * Deletes the `std::shared_ptr<T>` storage of the java object if exists
358 * and write `nullptr` into its `long nativeInstance` field.
359 *
360 * @tparam T
361 * @param env
362 * @param obj
363 */
364 template <typename T>
365 void clearInstance(JNIEnv *env, jobject obj) {
366 jfieldID instance_field = getInstanceField(env, obj);
368 {
369 const jlong nativeInstance = env->GetLongField(obj, instance_field);
371 std::shared_ptr<T>* other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
372 if( nullptr != other ) {
373 delete other;
374 }
375 }
376 env->SetLongField(obj, instance_field, 0);
378 }
379
380 /**
381 * A `std::shared_ptr<T>` storage instance to be copied from and released into a java object's `long nativeInstance` field.
382 *
383 * An instance holds a shared_ptr<T> storage pointer for a managed object T.
384 *
385 * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
386 *
387 * We prefer using `std::shared_ptr<T>` instead of a `naked pointer`,
388 * this way we automatically preserve the native instance lifecycle while within a JNI method.
389 *
390 * @tparam T the managed object type
391 */
392 template <typename T>
394 private:
395 std::shared_ptr<T>* ref_ptr;
396
397 void safe_delete() {
398 std::shared_ptr<T>* ref_ptr_ = ref_ptr;
399 ref_ptr = nullptr;
400 delete ref_ptr_;
401 }
402
403 static jlong get_instance(JNIEnv *env, jobject obj) {
404 if( nullptr != obj ) {
405 const jlong res = env->GetLongField(obj, getInstanceField(env, obj));
407 return res;
408 } else {
409 return 0;
410 }
411 }
412 static jlong get_instance(JNIEnv *env, jobject obj, jfieldID instance_field) {
413 if( nullptr != obj ) {
414 const jlong res = env->GetLongField(obj, instance_field);
416 return res;
417 } else {
418 return 0;
419 }
420 }
421
422 public:
423 /** Default constructor, nullptr */
424 shared_ptr_ref() noexcept
425 : ref_ptr( new std::shared_ptr<T>() )
426 { }
427
428 /** Copy constructor */
430 : ref_ptr( new std::shared_ptr<T>( o.shared_ptr() ) )
431 { }
432
433 /** Move constructor. */
435 : ref_ptr( o.ref_ptr )
436 {
437 o.ref_ptr = nullptr;
438 }
439
440 /** Assignment operator. */
442 if( this != &o ) {
443 if( nullptr != ref_ptr ) {
444 *ref_ptr = o.shared_ptr();
445 } else {
446 ref_ptr = new std::shared_ptr<T>( o.shared_ptr() );
447 }
448 }
449 return *this;
450 }
451
452 /** Move assignment operator. */
454 if( nullptr != ref_ptr ) {
455 safe_delete();
456 }
457 ref_ptr = o.ref_ptr;
458 o.ref_ptr = nullptr;
459 return *this;
460 }
461
463 if( nullptr != ref_ptr ) {
464 safe_delete();
465 }
466 }
467
468 /** Constructs a new instance, taking ownership of the given T pointer. */
469 shared_ptr_ref(T * ptr) noexcept
470 : ref_ptr( new std::shared_ptr<T>( ptr ) )
471 { }
472
473 /** Constructs a new instance, copying the given std::shared_ptr<T>. */
474 shared_ptr_ref(const std::shared_ptr<T>& ref) noexcept
475 : ref_ptr( new std::shared_ptr<T>( ref ) )
476 { }
477
478 /** Constructs a new instance, moving the given std::shared_ptr<T>. */
479 shared_ptr_ref(std::shared_ptr<T>&& ref) noexcept
480 : ref_ptr( new std::shared_ptr<T>( std::move(ref) ) )
481 { }
482
483 /** Assignment operator. */
484 shared_ptr_ref& operator=(const std::shared_ptr<T>& o) {
485 if( nullptr != ref_ptr ) {
486 *ref_ptr = o;
487 } else {
488 ref_ptr = new std::shared_ptr<T>( o );
489 }
490 return *this;
491 }
492
493 /**
494 * Throws an exception if this instances shared_ptr<T> storage is nullptr.
495 *
496 * The managed object reference may be nullptr.
497 */
498 void null_check1() const {
499 if (nullptr == ref_ptr) {
500 throw jau::RuntimeException("null reference store", E_FILE_LINE);
501 }
502 }
503
504 /**
505 * Throws an exception if either this instances shared_ptr<T> storage or
506 * the managed object reference is nullptr.
507 */
508 void null_check2() const {
509 if (nullptr == ref_ptr) {
510 throw jau::RuntimeException("null reference store", E_FILE_LINE);
511 }
512 if (nullptr == *ref_ptr) {
513 throw jau::RuntimeException("null reference", E_FILE_LINE);
514 }
515 }
516
517 /**
518 * Constructs a new instance, copying the instance from the given java `long nativeInstance` value,
519 * representing a java object's shared_ptr<T> storage
520 *
521 * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
522 *
523 * If `throw_on_nullptr` is true, throws an exception if either this instances shared_ptr<T> storage or
524 * the managed object reference is nullptr.
525 *
526 * @param nativeInstance the jlong representation of another shared_ptr<T> storage
527 * @param throw_on_nullptr if true, throws an exception if either this instances shared_ptr<T> storage or the managed object reference is nullptr.
528 */
529 shared_ptr_ref(jlong nativeInstance, const bool throw_on_nullptr=true)
530 : ref_ptr( new std::shared_ptr<T>() )
531 {
532 std::shared_ptr<T> * other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance);
533 if( nullptr != other && nullptr != *other ) {
534 *ref_ptr = *other;
535 }
536 if( throw_on_nullptr ) {
537 null_check2(); // exception if nullptr, even if other shared_ptr instance becomes nullptr @ copy-ctor
538 }
539 }
540
541 /**
542 * Constructs a new instance, copying the instance from the java object's `long nativeInstance` field.
543 * representing its shared_ptr<T> storage
544 *
545 * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
546 *
547 * If `throw_on_nullptr` is true, throws an exception if either this instances shared_ptr<T> storage or
548 * the managed object reference is nullptr.
549 *
550 * @param env denoting the JVM
551 * @param obj denoting the java object holding the `long nativeInstance` field, representing its shared_ptr<T> storage. Maybe `nullptr`, see `throw_on_nullptr`.
552 * @param throw_on_nullptr if true, throws an exception if either this instances shared_ptr<T> storage or the managed object reference is nullptr.
553 */
554 shared_ptr_ref(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true)
555 : shared_ptr_ref( get_instance(env, obj), throw_on_nullptr )
556 { }
557
558 /**
559 * Release ownership and returns the shared_ptr<T> storage.
560 *
561 * This instance shall not be used anymore.
562 */
563 std::shared_ptr<T>* release() noexcept {
564 const std::shared_ptr<T>* res = ref_ptr;
565 ref_ptr = nullptr;
566 return res;
567 }
568
569 /**
570 * Release ownership and return the jlong representation of the shared_ptr<T> storage.
571 *
572 * This instance shall not be used anymore.
573 */
574 jlong release_to_jlong() noexcept {
575 const jlong res = (jlong) (intptr_t)ref_ptr;
576 ref_ptr = nullptr;
577 return res;
578 }
579
580 /**
581 * Deletes the `std::shared_ptr<T>` storage of the target java object if exists first
582 * and writes this instance's `std::shared_ptr<T>` storage pointer into its `long nativeInstance` field,
583 * then releases ownership, see release_to_jlong().
584 *
585 * This instance shall not be used anymore.
586 *
587 * Throws an exception if either this instances shared_ptr<T> storage or
588 * the managed object reference is nullptr.
589 *
590 * @param env
591 * @param obj the target java object
592 */
593 void release_into_object(JNIEnv *env, jobject obj) {
594 null_check2();
595 if( nullptr == obj ) {
596 throw jau::RuntimeException("null target object", E_FILE_LINE);
597 }
598 jfieldID instance_field = getInstanceField(env, obj);
600 {
601 std::shared_ptr<T> * other = reinterpret_cast<std::shared_ptr<T> *>( get_instance(env, obj, instance_field) );
602 if( nullptr != other ) {
603 delete other;
604 }
605 }
606 env->SetLongField(obj, instance_field, release_to_jlong());
608 }
609
610 /**
611 * Returns true if either this instances shared_ptr<T> storage or
612 * the managed object reference is nullptr.
613 */
614 bool is_null() const noexcept {
615 return nullptr == ref_ptr || nullptr == *ref_ptr;
616 }
617
618 /**
619 * Provides access to the shared_ptr<T> pointer, l-value of storage.
620 */
621 std::shared_ptr<T>* pointer() noexcept {
622 return ref_ptr;
623 }
624
625 /**
626 * Provides access to const reference of shared_ptr<T>, r-value.
627 *
628 * Throws an exception if this instances shared_ptr<T> storage is nullptr.
629 */
630 const std::shared_ptr<T>& shared_ptr() const {
631 null_check1();
632 return *ref_ptr;
633 }
634
635 /**
636 * Provides access to reference of stored T.
637 *
638 * Throws an exception if either this instances shared_ptr<T> storage or
639 * the managed object reference is nullptr.
640 */
642 null_check2();
643 return *(ref_ptr->get());
644 }
645
646 /**
647 * Provides access to pointer of stored T.
648 *
649 * Throws an exception if either this instances shared_ptr<T> storage or
650 * the managed object reference is nullptr.
651 */
653 null_check2();
654 return ref_ptr->get();
655 }
656
657 std::string toString() const noexcept {
658 return "shared_ptr_ref[ ptr "+jau::to_hexstring(ref_ptr)+
659 ", obj "+ ( nullptr != ref_ptr ? jau::to_hexstring(ref_ptr->get()) : "null" ) + "]";
660 }
661 };
662
663 //
664 // C++ <-> java type mapping
665 //
666
667 template <typename T>
668 jobject convert_instance_to_jobject(JNIEnv *env, const std::shared_ptr<T>& elem,
669 const char *ctor_prototype, jau::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<T>&)> ctor)
670 {
671 jclass clazz = search_class(env, T::java_class().c_str());
672 jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
673
674 jobject object = ctor(env, clazz, clazz_ctor, elem);
675 if (!object)
676 {
677 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
678 }
680
681 return object;
682 }
683
684 template <typename T>
685 jobject convert_instance_to_jobject(JNIEnv *env, jclass clazz,
686 const char *ctor_prototype, jau::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<T>&)> ctor,
687 const std::shared_ptr<T>& elem)
688 {
689 jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
690
691 jobject object = ctor(env, clazz, clazz_ctor, elem);
692 if (!object)
693 {
694 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
695 }
697
698 return object;
699 }
700
701 template <typename T>
702 jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array)
703 {
704 nsize_t array_size = array.size();
705
706 jmethodID arraylist_add;
707 jobject result = get_new_arraylist(env, (jsize)array_size, &arraylist_add);
708
709 if (0 == array_size) {
710 return result;
711 }
712
713 jau::for_each(array.begin(), array.end(), [&](typename T::value_type & elem){
714 JavaAnonRef objref = elem->getJavaObject();
715 if ( nullptr == objref ) {
716 throw InternalError("JavaUplink element of array has no valid java-object: "+elem->toString(), E_FILE_LINE);
717 }
718 env->CallBooleanMethod(result, arraylist_add, JavaGlobalObj::GetObject(objref));
719 });
720 return result;
721 }
722
723 template <typename T, typename U>
724 jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array,
725 const char *ctor_prototype, jau::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<U>&)> ctor)
726 {
727 const size_t array_size = array.size();
728 if( array_size > std::numeric_limits<jsize>::max() ) {
729 throw jau::RuntimeException("Native array size "+std::to_string(array_size)+
731 }
732 const jsize jarray_size = array_size;
733
734 jmethodID arraylist_add;
735 jobject result = get_new_arraylist(env, jarray_size, &arraylist_add);
736
737 if (jarray_size == 0)
738 {
739 return result;
740 }
741
742 jclass clazz = search_class(env, U::java_class().c_str());
743 jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
744
745 for (jsize i = 0; i < jarray_size; ++i)
746 {
747 jobject object = ctor(env, clazz, clazz_ctor, array[i] /* const std::shared_ptr<U>& */);
748 if (!object)
749 {
750 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
751 }
752 env->CallBooleanMethod(result, arraylist_add, object);
754 }
755 return result;
756 }
757
758 template <typename T, typename U>
759 jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array, jau::function<jobject(JNIEnv*, const std::shared_ptr<U>&)> ctor)
760 {
761 const size_t array_size = array.size();
762 if( array_size > std::numeric_limits<jsize>::max() ) {
763 throw jau::RuntimeException("Native array size "+std::to_string(array_size)+
765 }
766 const jsize jarray_size = array_size;
767
768 jmethodID arraylist_add;
769 jobject result = get_new_arraylist(env, jarray_size, &arraylist_add);
770
771 if (jarray_size == 0)
772 {
773 return result;
774 }
775
776 for (jsize i = 0; i < jarray_size; ++i)
777 {
778 jobject object = ctor(env, array[i] /* const std::shared_ptr<U>& */);
779 if (!object)
780 {
781 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
782 }
783 env->CallBooleanMethod(result, arraylist_add, object);
785 }
786 return result;
787 }
788
789 template <typename T, typename U>
790 jobject convert_vector_to_jarraylist(JNIEnv *env, T& array, jau::function<jobject(JNIEnv*, const U&)> ctor)
791 {
792 const size_t array_size = array.size();
793 if( array_size > std::numeric_limits<jsize>::max() ) {
794 throw jau::RuntimeException("Native array size "+std::to_string(array_size)+
796 }
797 const jsize jarray_size = array_size;
798
799 jmethodID arraylist_add;
800 jobject result = get_new_arraylist(env, jarray_size, &arraylist_add);
801
802 if (jarray_size == 0)
803 {
804 return result;
805 }
806
807 for (jsize i = 0; i < jarray_size; ++i)
808 {
809 jobject object = ctor(env, array[i] /* const U& */);
810 if (!object)
811 {
812 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
813 }
814 env->CallBooleanMethod(result, arraylist_add, object);
816 }
817 return result;
818 }
819
820 /**@}*/
821
822
823} // namespace jau::jni
824
825#endif /* JAU_HELPER_JNI_HPP_ */
#define E_FILE_LINE
Class template jau::function is a general-purpose static-polymorphic function wrapper.
jobject getObject() const noexcept
jclass getClass() const noexcept
Definition: jni_mem.hpp:126
Pure virtual JavaAnon, hiding Java JNI details from API, to be implemented by JNI module.
Definition: java_uplink.hpp:50
Implementation for JavaAnon, by simply wrapping a JNIGlobalRef instance.
Definition: helper_jni.hpp:166
~JavaGlobalObj() noexcept override
JavaGlobalObj & operator=(const JavaGlobalObj &o) noexcept=default
JavaGlobalObj(const JNIGlobalRef &obj, jmethodID mNotifyDeleted_) noexcept
Definition: helper_jni.hpp:210
static jobject checkAndGetObject(const JavaAnonRef &shref, const char *file, int line)
Definition: helper_jni.hpp:184
JavaGlobalObj(JNIGlobalRef &&obj, jmethodID mNotifyDeleted_) noexcept
Definition: helper_jni.hpp:213
jobject getObject() const noexcept
Definition: helper_jni.hpp:232
static jobject GetObject(const JavaAnonRef &shref) noexcept
Definition: helper_jni.hpp:241
static bool isValid(const JavaAnonRef &shref) noexcept
Definition: helper_jni.hpp:197
JavaGlobalObj(jobject obj, jmethodID mNotifyDeleted_) noexcept
Definition: helper_jni.hpp:207
const JNIGlobalRef & getJavaObject() const noexcept
Definition: helper_jni.hpp:228
std::string toString() const noexcept override
Definition: helper_jni.hpp:223
JavaGlobalObj(JavaGlobalObj &&o) noexcept=default
static void check(const JavaAnonRef &shref, const char *file, int line)
Definition: helper_jni.hpp:172
JavaGlobalObj(const JavaGlobalObj &o) noexcept=default
static JNIGlobalRef GetJavaObject(const JavaAnonRef &shref) noexcept
Definition: helper_jni.hpp:237
JNIGlobalRef getJavaObject() noexcept
Definition: helper_jni.hpp:229
static jclass GetClass(const JavaAnonRef &shref) noexcept
Definition: helper_jni.hpp:246
jclass getClass() const noexcept
Definition: helper_jni.hpp:234
JavaGlobalObj & operator=(JavaGlobalObj &&o) noexcept=default
A std::shared_ptr<T> storage instance to be copied from and released into a java object's long native...
Definition: helper_jni.hpp:393
void null_check2() const
Throws an exception if either this instances shared_ptr<T> storage or the managed object reference is...
Definition: helper_jni.hpp:508
void null_check1() const
Throws an exception if this instances shared_ptr<T> storage is nullptr.
Definition: helper_jni.hpp:498
bool is_null() const noexcept
Returns true if either this instances shared_ptr<T> storage or the managed object reference is nullpt...
Definition: helper_jni.hpp:614
shared_ptr_ref(jlong nativeInstance, const bool throw_on_nullptr=true)
Constructs a new instance, copying the instance from the given java long nativeInstance value,...
Definition: helper_jni.hpp:529
T * operator->()
Provides access to pointer of stored T.
Definition: helper_jni.hpp:652
shared_ptr_ref(const std::shared_ptr< T > &ref) noexcept
Constructs a new instance, copying the given std::shared_ptr<T>.
Definition: helper_jni.hpp:474
shared_ptr_ref(std::shared_ptr< T > &&ref) noexcept
Constructs a new instance, moving the given std::shared_ptr<T>.
Definition: helper_jni.hpp:479
const std::shared_ptr< T > & shared_ptr() const
Provides access to const reference of shared_ptr<T>, r-value.
Definition: helper_jni.hpp:630
shared_ptr_ref(const shared_ptr_ref &o) noexcept
Copy constructor.
Definition: helper_jni.hpp:429
std::shared_ptr< T > * pointer() noexcept
Provides access to the shared_ptr<T> pointer, l-value of storage.
Definition: helper_jni.hpp:621
std::shared_ptr< T > * release() noexcept
Release ownership and returns the shared_ptr<T> storage.
Definition: helper_jni.hpp:563
std::string toString() const noexcept
Definition: helper_jni.hpp:657
shared_ptr_ref & operator=(shared_ptr_ref &&o) noexcept
Move assignment operator.
Definition: helper_jni.hpp:453
T & operator*()
Provides access to reference of stored T.
Definition: helper_jni.hpp:641
jlong release_to_jlong() noexcept
Release ownership and return the jlong representation of the shared_ptr<T> storage.
Definition: helper_jni.hpp:574
shared_ptr_ref(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true)
Constructs a new instance, copying the instance from the java object's long nativeInstance field.
Definition: helper_jni.hpp:554
shared_ptr_ref(T *ptr) noexcept
Constructs a new instance, taking ownership of the given T pointer.
Definition: helper_jni.hpp:469
shared_ptr_ref(shared_ptr_ref &&o) noexcept
Move constructor.
Definition: helper_jni.hpp:434
shared_ptr_ref() noexcept
Default constructor, nullptr.
Definition: helper_jni.hpp:424
void release_into_object(JNIEnv *env, jobject obj)
Deletes the std::shared_ptr<T> storage of the target java object if exists first and writes this inst...
Definition: helper_jni.hpp:593
shared_ptr_ref & operator=(const shared_ptr_ref &o)
Assignment operator.
Definition: helper_jni.hpp:441
shared_ptr_ref & operator=(const std::shared_ptr< T > &o)
Assignment operator.
Definition: helper_jni.hpp:484
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
Like std::for_each() of 'algorithm'.
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
std::basic_string< char, std::char_traits< char >, jau::callocator_sec< char > > secure_string
Definition: io_util.hpp:48
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
constexpr T max(const T x, const T y) noexcept
Returns the maximum of two integrals (w/ branching) in O(1)
Definition: base_math.hpp:191
std::shared_ptr< JavaGlobalObj > JavaGlobalObjRef
Definition: helper_jni.hpp:250
jint getIntFieldValue(JNIEnv *env, jobject obj, const char *field_name)
void java_exception_check_and_throw(JNIEnv *env, const char *file, int line)
Throws a C++ exception if a java exception occurred, otherwise do nothing.
void print_native_caught_exception_fwd2java(const jau::OutOfMemoryError &e, const char *file, int line)
void raise_java_exception(JNIEnv *env, const std::exception &e, const char *file, int line)
jfieldID getField(JNIEnv *env, jobject obj, const char *field_name, const char *field_signature)
jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T &array, jau::function< jobject(JNIEnv *, const std::shared_ptr< U > &)> ctor)
Definition: helper_jni.hpp:759
std::shared_ptr< T > * castInstance(jlong instance, const bool throw_on_nullptr=true)
Returns the cast shared_ptr<T> pointer from the java object's long nativeInstance field.
Definition: helper_jni.hpp:286
jclass search_class(JNIEnv *env, JavaUplink &object)
void clearInstance(JNIEnv *env, jobject obj)
Deletes the std::shared_ptr<T> storage of the java object if exists and write nullptr into its long n...
Definition: helper_jni.hpp:365
jfieldID getInstanceField(JNIEnv *env, jobject obj)
Definition: helper_jni.hpp:115
jobject convert_vector_to_jarraylist(JNIEnv *env, T &array, jau::function< jobject(JNIEnv *, const U &)> ctor)
Definition: helper_jni.hpp:790
std::shared_ptr< T > * getInstance(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true)
Returns the cast shared_ptr<T> pointer from the java object's long nativeInstance field.
Definition: helper_jni.hpp:309
void setInstance(JNIEnv *env, jobject obj, const std::shared_ptr< T > &t)
Deletes the std::shared_ptr<T> storage of the java object if exists first and writes the given std::s...
Definition: helper_jni.hpp:334
std::vector< std::string > convert_jlist_string_to_vector(JNIEnv *env, jobject jlist)
std::string getStringFieldValue(JNIEnv *env, jobject obj, const char *field_name)
jstring from_string_to_jstring(JNIEnv *env, const std::string &str)
jlong getLongFieldValue(JNIEnv *env, jobject obj, const char *field_name)
jobject convert_instance_to_jobject(JNIEnv *env, const std::shared_ptr< T > &elem, const char *ctor_prototype, jau::function< jobject(JNIEnv *, jclass, jmethodID, const std::shared_ptr< T > &)> ctor)
Definition: helper_jni.hpp:668
void rethrow_and_raise_java_exception_jauimpl(JNIEnv *env, const char *file, int line)
Re-throw current exception and raise respective java exception using any matching function above.
jbyteArray convert_bytes_to_jbytearray(JNIEnv *env, const byte_container_type &data)
Definition: helper_jni.hpp:150
jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T &array)
Definition: helper_jni.hpp:702
jfieldID search_field(JNIEnv *env, jclass clazz, const char *field_name, const char *type, bool is_static)
void setObjectRef(JNIEnv *env, jobject obj, T *t, const char *field_name)
Definition: helper_jni.hpp:268
jobject getObjectFieldValue(JNIEnv *env, jobject obj, const char *field_name, const char *field_signature)
jobject convert_vector_stringview_to_jarraylist(JNIEnv *env, const std::vector< std::string_view > &array)
bool java_exception_check(JNIEnv *env, const char *file, int line)
Return true if a java exception occurred, otherwise false.
jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, const char *prototype, bool is_static)
std::shared_ptr< JavaAnon > JavaAnonRef
Definition: java_uplink.hpp:55
jobject convert_vector_string_to_jarraylist(JNIEnv *env, const std::vector< std::string > &array)
T * getObjectRef(JNIEnv *env, jobject obj, const char *field_name)
Definition: helper_jni.hpp:260
jau::io::secure_string from_jbytebuffer_to_sstring(JNIEnv *env, jobject jbytebuffer)
jobject get_new_arraylist(JNIEnv *env, jsize size, jmethodID *add)
std::string from_jstring_to_string(JNIEnv *env, jstring str)
bool from_jboolean_to_bool(const jboolean val)
jobject convert_vector_bytes_to_jarraylist(JNIEnv *env, const std::vector< std::vector< uint8_t > > &array)
jclass search_class(JNIEnv *env, const char *clazz_name)
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
STL namespace.