jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
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::ExceptionBase &e, const char* file, int line);
79 void print_native_caught_exception_fwd2java(const std::exception &e, const char* file, int line);
80 void print_native_caught_exception_fwd2java(const std::string &msg, const char* file, int line);
81 void print_native_caught_exception_fwd2java(const char * cmsg, const char* file, int line);
82
83 void raise_java_exception(JNIEnv *env, const jau::ExceptionBase &e, const char* file, int line);
84 void raise_java_exception(JNIEnv *env, const jau::RuntimeExceptionBase &e, const char* file, int line);
85 void raise_java_exception(JNIEnv *env, const jau::InternalError &e, const char* file, int line);
86 void raise_java_exception(JNIEnv *env, const jau::NullPointerException &e, const char* file, int line);
87 void raise_java_exception(JNIEnv *env, const jau::IllegalArgumentError &e, const char* file, int line);
88 void raise_java_exception(JNIEnv *env, const jau::IllegalStateError &e, const char* file, int line);
89 void raise_java_exception(JNIEnv *env, const jau::UnsupportedOperationException &e, const char* file, int line);
90 void raise_java_exception(JNIEnv *env, const jau::IndexOutOfBoundsError &e, const char* file, int line);
91 void raise_java_exception(JNIEnv *env, const jau::OutOfMemoryError &e, const char* file, int line);
92 void raise_java_exception(JNIEnv *env, const std::exception &e, const char* file, int line);
93 void raise_java_exception(JNIEnv *env, const std::runtime_error &e, const char* file, int line);
94 void raise_java_exception(JNIEnv *env, const std::invalid_argument &e, const char* file, int line);
95 void raise_java_exception(JNIEnv *env, const std::bad_alloc &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 return "JavaGlobalObj["+jau::to_hexstring(javaObjectRef.getObject())+"]";
225 }
226
227 const JNIGlobalRef & getJavaObject() const noexcept { return javaObjectRef; }
228 JNIGlobalRef getJavaObject() noexcept { return javaObjectRef; }
229
230 /* Provides access to the stored GlobalRef as an jobject. */
231 jobject getObject() const noexcept { return javaObjectRef.getObject(); }
232 /* Provides access to the stored GlobalRef as a jclass. */
233 jclass getClass() const noexcept { return javaObjectRef.getClass(); }
234
235 /* Provides access to the stored GlobalRef as an getJavaObject. */
236 static JNIGlobalRef GetJavaObject(const JavaAnonRef & shref) noexcept {
237 return static_cast<JavaGlobalObj*>(shref.get())->getJavaObject();
238 }
239 /* Provides access to the stored GlobalRef as an jobject. */
240 static jobject GetObject(const JavaAnonRef & shref) noexcept {
241 return static_cast<JavaGlobalObj*>(shref.get())->getObject();
242 }
243
244 /* Provides access to the stored GlobalRef as a jclass. */
245 static jclass GetClass(const JavaAnonRef & shref) noexcept {
246 return static_cast<JavaGlobalObj*>(shref.get())->getClass();
247 }
248 };
249 typedef std::shared_ptr<JavaGlobalObj> JavaGlobalObjRef;
250
251 //
252 // C++ JavaAnon <-> java access, all generic
253 //
254 // We prefer using `std::shared_ptr<T>` instead of a `naked pointer`,
255 // this way we automatically preserve the native instance lifecycle while within a JNI method.
256 //
257
258 template <typename T>
259 T *getObjectRef(JNIEnv *env, jobject obj, const char* field_name)
260 {
261 jlong jobj = env->GetLongField(obj, getField(env, obj, field_name, "J"));
263 return reinterpret_cast<T *>(jobj);
264 }
265
266 template <typename T>
267 void setObjectRef(JNIEnv *env, jobject obj, T *t, const char* field_name)
268 {
269 jlong jobj = reinterpret_cast<jlong>(t);
270 env->SetLongField(obj, getField(env, obj, field_name, "J"), jobj);
272 }
273
274 /**
275 * Returns the cast `shared_ptr<T>` pointer from the java object's `long nativeInstance` field.
276 *
277 * If `throw_on_nullptr` is true, throws an exception if the shared_ptr<T> pointer is nullptr.
278 *
279 * @tparam T
280 * @param instance
281 * @param throw_on_nullptr
282 * @return
283 */
284 template <typename T>
285 std::shared_ptr<T> * castInstance(jlong instance, const bool throw_on_nullptr=true)
286 {
287 std::shared_ptr<T> * ref_ptr = reinterpret_cast<std::shared_ptr<T> *>(instance); // NOLINT(performance-no-int-to-ptr): Required and intended
288 if( throw_on_nullptr ) {
289 if (nullptr == ref_ptr) {
290 throw jau::RuntimeException("null reference store", E_FILE_LINE);
291 }
292 }
293 return ref_ptr;
294 }
295
296 /**
297 * Returns the cast `shared_ptr<T>` pointer from the java object's `long nativeInstance` field.
298 *
299 * If `throw_on_nullptr` is true, throws an exception if either the shared_ptr<T> pointer or
300 * its managed object reference is nullptr.
301 *
302 * @tparam T
303 * @param env
304 * @param obj
305 * @param throw_on_nullptr if true, throws exception if instance reference is nullptr (default). Otherwise not.
306 */
307 template <typename T>
308 std::shared_ptr<T>* getInstance(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true) {
309 const jlong nativeInstance = env->GetLongField(obj, getInstanceField(env, obj));
311 std::shared_ptr<T>* ref_ptr = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance); // NOLINT(performance-no-int-to-ptr): Required and intended
312 if( throw_on_nullptr ) {
313 if (nullptr == ref_ptr) {
314 throw jau::RuntimeException("null reference store", E_FILE_LINE);
315 }
316 if (nullptr == *ref_ptr) {
317 throw jau::RuntimeException("null reference", E_FILE_LINE);
318 }
319 }
320 return ref_ptr;
321 }
322
323 /**
324 * Deletes the `std::shared_ptr<T>` storage of the java object if exists first
325 * and writes the given `std::shared_ptr<T>` storage pointer into its `long nativeInstance` field.
326 *
327 * @tparam T
328 * @param env
329 * @param obj
330 * @param t
331 */
332 template <typename T>
333 void setInstance(JNIEnv *env, jobject obj, const std::shared_ptr<T>& t)
334 {
335 if (t == nullptr) {
336 throw jau::RuntimeException("Trying to create null object", E_FILE_LINE);
337 }
338 const jlong instance = (jlong) (intptr_t) &t;
339
340 jfieldID instance_field = getInstanceField(env, obj);
342 {
343 const jlong nativeInstance = env->GetLongField(obj, instance_field);
345 std::shared_ptr<T>* other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance); // NOLINT(performance-no-int-to-ptr): Required and intended
346 if( nullptr != other ) {
347 delete other;
348 }
349 }
350 env->SetLongField(obj, instance_field, instance);
352 }
353
354
355 /**
356 * Deletes the `std::shared_ptr<T>` storage of the java object if exists
357 * and write `nullptr` into its `long nativeInstance` field.
358 *
359 * @tparam T
360 * @param env
361 * @param obj
362 */
363 template <typename T>
364 void clearInstance(JNIEnv *env, jobject obj) {
365 jfieldID instance_field = getInstanceField(env, obj);
367 {
368 const jlong nativeInstance = env->GetLongField(obj, instance_field);
370 std::shared_ptr<T>* other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance); // NOLINT(performance-no-int-to-ptr): Required and intended
371 if( nullptr != other ) {
372 delete other;
373 }
374 }
375 env->SetLongField(obj, instance_field, 0);
377 }
378
379 /**
380 * A `std::shared_ptr<T>` storage instance to be copied from and released into a java object's `long nativeInstance` field.
381 *
382 * An instance holds a shared_ptr<T> storage pointer for a managed object T.
383 *
384 * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
385 *
386 * We prefer using `std::shared_ptr<T>` instead of a `naked pointer`,
387 * this way we automatically preserve the native instance lifecycle while within a JNI method.
388 *
389 * @tparam T the managed object type
390 */
391 template <typename T>
393 private:
394 std::shared_ptr<T>* ref_ptr;
395
396 void safe_delete() {
397 std::shared_ptr<T>* ref_ptr_ = ref_ptr;
398 ref_ptr = nullptr;
399 delete ref_ptr_;
400 }
401
402 static jlong get_instance(JNIEnv *env, jobject obj) {
403 if( nullptr != obj ) {
404 const jlong res = env->GetLongField(obj, getInstanceField(env, obj));
406 return res;
407 } else {
408 return 0;
409 }
410 }
411 static jlong get_instance(JNIEnv *env, jobject obj, jfieldID instance_field) {
412 if( nullptr != obj ) {
413 const jlong res = env->GetLongField(obj, instance_field);
415 return res;
416 } else {
417 return 0;
418 }
419 }
420
421 public:
422 /** Default constructor, nullptr */
423 shared_ptr_ref() noexcept
424 : ref_ptr( new std::shared_ptr<T>() )
425 { }
426
427 /** Copy constructor */
429 : ref_ptr( new std::shared_ptr<T>( o.shared_ptr() ) )
430 { }
431
432 /** Move constructor. */
434 : ref_ptr( o.ref_ptr )
435 {
436 o.ref_ptr = nullptr;
437 }
438
439 /** Assignment operator. */
441 if( this != &o ) {
442 if( nullptr != ref_ptr ) {
443 *ref_ptr = o.shared_ptr();
444 } else {
445 ref_ptr = new std::shared_ptr<T>( o.shared_ptr() );
446 }
447 }
448 return *this;
449 }
450
451 /** Move assignment operator. */
453 if( nullptr != ref_ptr ) {
454 safe_delete();
455 }
456 ref_ptr = o.ref_ptr;
457 o.ref_ptr = nullptr;
458 return *this;
459 }
460
462 if( nullptr != ref_ptr ) {
463 safe_delete();
464 }
465 }
466
467 /** Constructs a new instance, taking ownership of the given T pointer. */
469 : ref_ptr( new std::shared_ptr<T>( ptr ) )
470 { }
471
472 /** Constructs a new instance, copying the given std::shared_ptr<T>. */
473 shared_ptr_ref(const std::shared_ptr<T>& ref)
474 : ref_ptr( new std::shared_ptr<T>( ref ) )
475 { }
476
477 /** Constructs a new instance, moving the given std::shared_ptr<T>. */
478 shared_ptr_ref(std::shared_ptr<T>&& ref) noexcept
479 : ref_ptr( new std::shared_ptr<T>( std::move(ref) ) )
480 { }
481
482 /** Assignment operator. */
483 shared_ptr_ref& operator=(const std::shared_ptr<T>& o) {
484 if( nullptr != ref_ptr ) {
485 *ref_ptr = o;
486 } else {
487 ref_ptr = new std::shared_ptr<T>( o );
488 }
489 return *this;
490 }
491
492 /**
493 * Throws an exception if this instances shared_ptr<T> storage is nullptr.
494 *
495 * The managed object reference may be nullptr.
496 */
497 void null_check1() const {
498 if (nullptr == ref_ptr) {
499 throw jau::RuntimeException("null reference store", E_FILE_LINE);
500 }
501 }
502
503 /**
504 * Throws an exception if either this instances shared_ptr<T> storage or
505 * the managed object reference is nullptr.
506 */
507 void null_check2() const {
508 if (nullptr == ref_ptr) {
509 throw jau::RuntimeException("null reference store", E_FILE_LINE);
510 }
511 if (nullptr == *ref_ptr) {
512 throw jau::RuntimeException("null reference", E_FILE_LINE);
513 }
514 }
515
516 /**
517 * Constructs a new instance, copying the instance from the given java `long nativeInstance` value,
518 * representing a java object's shared_ptr<T> storage
519 *
520 * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
521 *
522 * If `throw_on_nullptr` is true, throws an exception if either this instances shared_ptr<T> storage or
523 * the managed object reference is nullptr.
524 *
525 * @param nativeInstance the jlong representation of another shared_ptr<T> storage
526 * @param throw_on_nullptr if true, throws an exception if either this instances shared_ptr<T> storage or the managed object reference is nullptr.
527 */
528 shared_ptr_ref(jlong nativeInstance, const bool throw_on_nullptr=true)
529 : ref_ptr( new std::shared_ptr<T>() )
530 {
531 std::shared_ptr<T> * other = reinterpret_cast<std::shared_ptr<T> *>(nativeInstance); // NOLINT(performance-no-int-to-ptr): Required and intended
532 if( nullptr != other && nullptr != *other ) {
533 *ref_ptr = *other;
534 }
535 if( throw_on_nullptr ) {
536 null_check2(); // exception if nullptr, even if other shared_ptr instance becomes nullptr @ copy-ctor
537 }
538 }
539
540 /**
541 * Constructs a new instance, copying the instance from the java object's `long nativeInstance` field.
542 * representing its shared_ptr<T> storage
543 *
544 * Using a `shared_ptr<T>` copy increments its reference counter and prohibits its destruction while in use.
545 *
546 * If `throw_on_nullptr` is true, throws an exception if either this instances shared_ptr<T> storage or
547 * the managed object reference is nullptr.
548 *
549 * @param env denoting the JVM
550 * @param obj denoting the java object holding the `long nativeInstance` field, representing its shared_ptr<T> storage. Maybe `nullptr`, see `throw_on_nullptr`.
551 * @param throw_on_nullptr if true, throws an exception if either this instances shared_ptr<T> storage or the managed object reference is nullptr.
552 */
553 shared_ptr_ref(JNIEnv *env, jobject obj, const bool throw_on_nullptr=true)
554 : shared_ptr_ref( get_instance(env, obj), throw_on_nullptr )
555 { }
556
557 /**
558 * Release ownership and returns the shared_ptr<T> storage.
559 *
560 * This instance shall not be used anymore.
561 */
562 std::shared_ptr<T>* release() noexcept {
563 const std::shared_ptr<T>* res = ref_ptr;
564 ref_ptr = nullptr;
565 return res;
566 }
567
568 /**
569 * Release ownership and return the jlong representation of the shared_ptr<T> storage.
570 *
571 * This instance shall not be used anymore.
572 */
573 jlong release_to_jlong() noexcept {
574 const jlong res = (jlong) (intptr_t)ref_ptr;
575 ref_ptr = nullptr;
576 return res;
577 }
578
579 /**
580 * Deletes the `std::shared_ptr<T>` storage of the target java object if exists first
581 * and writes this instance's `std::shared_ptr<T>` storage pointer into its `long nativeInstance` field,
582 * then releases ownership, see release_to_jlong().
583 *
584 * This instance shall not be used anymore.
585 *
586 * Throws an exception if either this instances shared_ptr<T> storage or
587 * the managed object reference is nullptr.
588 *
589 * @param env
590 * @param obj the target java object
591 */
592 void release_into_object(JNIEnv *env, jobject obj) {
593 null_check2();
594 if( nullptr == obj ) {
595 throw jau::RuntimeException("null target object", E_FILE_LINE);
596 }
597 jfieldID instance_field = getInstanceField(env, obj);
599 {
600 std::shared_ptr<T> * other = reinterpret_cast<std::shared_ptr<T> *>( get_instance(env, obj, instance_field) ); // NOLINT(performance-no-int-to-ptr): Required and intended
601 if( nullptr != other ) {
602 delete other;
603 }
604 }
605 env->SetLongField(obj, instance_field, release_to_jlong());
607 }
608
609 /**
610 * Returns true if either this instances shared_ptr<T> storage or
611 * the managed object reference is nullptr.
612 */
613 bool is_null() const noexcept {
614 return nullptr == ref_ptr || nullptr == *ref_ptr;
615 }
616
617 /**
618 * Provides access to the shared_ptr<T> pointer, l-value of storage.
619 */
620 std::shared_ptr<T>* pointer() noexcept {
621 return ref_ptr;
622 }
623
624 /**
625 * Provides access to const reference of shared_ptr<T>, r-value.
626 *
627 * Throws an exception if this instances shared_ptr<T> storage is nullptr.
628 */
629 const std::shared_ptr<T>& shared_ptr() const {
630 null_check1();
631 return *ref_ptr;
632 }
633
634 /**
635 * Provides access to reference of stored T.
636 *
637 * Throws an exception if either this instances shared_ptr<T> storage or
638 * the managed object reference is nullptr.
639 */
641 null_check2();
642 return *(ref_ptr->get());
643 }
644
645 /**
646 * Provides access to pointer of stored T.
647 *
648 * Throws an exception if either this instances shared_ptr<T> storage or
649 * the managed object reference is nullptr.
650 */
652 null_check2();
653 return ref_ptr->get();
654 }
655
656 std::string toString() const noexcept {
657 return "shared_ptr_ref[ ptr "+jau::to_hexstring(ref_ptr)+
658 ", obj "+ ( nullptr != ref_ptr ? jau::to_hexstring(ref_ptr->get()) : "null" ) + "]";
659 }
660 };
661
662 //
663 // C++ <-> java type mapping
664 //
665
666 template <typename T>
667 jobject convert_instance_to_jobject(JNIEnv *env, const std::shared_ptr<T>& elem,
668 const char *ctor_prototype, jau::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<T>&)> ctor)
669 {
670 jclass clazz = search_class(env, T::java_class().c_str());
671 jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
672
673 jobject object = ctor(env, clazz, clazz_ctor, elem);
674 if (!object)
675 {
676 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
677 }
679
680 return object;
681 }
682
683 template <typename T>
684 jobject convert_instance_to_jobject(JNIEnv *env, jclass clazz,
685 const char *ctor_prototype, jau::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<T>&)> ctor,
686 const std::shared_ptr<T>& elem)
687 {
688 jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
689
690 jobject object = ctor(env, clazz, clazz_ctor, elem);
691 if (!object)
692 {
693 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
694 }
696
697 return object;
698 }
699
700 template <typename T>
701 jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array)
702 {
703 nsize_t array_size = array.size();
704
705 jmethodID arraylist_add;
706 jobject result = get_new_arraylist(env, (jsize)array_size, &arraylist_add);
707
708 if (0 == array_size) {
709 return result;
710 }
711
712 jau::for_each(array.begin(), array.end(), [&](typename T::value_type & elem){
713 JavaAnonRef objref = elem->getJavaObject();
714 if ( nullptr == objref ) {
715 throw InternalError("JavaUplink element of array has no valid java-object: "+elem->toString(), E_FILE_LINE);
716 }
717 env->CallBooleanMethod(result, arraylist_add, JavaGlobalObj::GetObject(objref));
718 });
719 return result;
720 }
721
722 template <typename T, typename U>
723 jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array,
724 const char *ctor_prototype, jau::function<jobject(JNIEnv*, jclass, jmethodID, const std::shared_ptr<U>&)> ctor)
725 {
726 const size_t array_size = array.size();
727 if( array_size > std::numeric_limits<jsize>::max() ) {
728 throw jau::RuntimeException("Native array size "+std::to_string(array_size)+
729 " exceeds max jsize "+std::to_string(std::numeric_limits<jsize>::max()), E_FILE_LINE);
730 }
731 const jsize jarray_size = array_size;
732
733 jmethodID arraylist_add;
734 jobject result = get_new_arraylist(env, jarray_size, &arraylist_add);
735
736 if (jarray_size == 0)
737 {
738 return result;
739 }
740
741 jclass clazz = search_class(env, U::java_class().c_str());
742 jmethodID clazz_ctor = search_method(env, clazz, "<init>", ctor_prototype, false);
743
744 for (jsize i = 0; i < jarray_size; ++i)
745 {
746 jobject object = ctor(env, clazz, clazz_ctor, array[i] /* const std::shared_ptr<U>& */);
747 if (!object)
748 {
749 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
750 }
751 env->CallBooleanMethod(result, arraylist_add, object);
753 }
754 return result;
755 }
756
757 template <typename T, typename U>
758 jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T& array, jau::function<jobject(JNIEnv*, const std::shared_ptr<U>&)> ctor)
759 {
760 const size_t array_size = array.size();
761 if( array_size > std::numeric_limits<jsize>::max() ) {
762 throw jau::RuntimeException("Native array size "+std::to_string(array_size)+
763 " exceeds max jsize "+std::to_string(std::numeric_limits<jsize>::max()), E_FILE_LINE);
764 }
765 const jsize jarray_size = array_size;
766
767 jmethodID arraylist_add;
768 jobject result = get_new_arraylist(env, jarray_size, &arraylist_add);
769
770 if (jarray_size == 0)
771 {
772 return result;
773 }
774
775 for (jsize i = 0; i < jarray_size; ++i)
776 {
777 jobject object = ctor(env, array[i] /* const std::shared_ptr<U>& */);
778 if (!object)
779 {
780 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
781 }
782 env->CallBooleanMethod(result, arraylist_add, object);
784 }
785 return result;
786 }
787
788 template <typename T, typename U>
789 jobject convert_vector_to_jarraylist(JNIEnv *env, T& array, jau::function<jobject(JNIEnv*, const U&)> ctor)
790 {
791 const size_t array_size = array.size();
792 if( array_size > std::numeric_limits<jsize>::max() ) {
793 throw jau::RuntimeException("Native array size "+std::to_string(array_size)+
794 " exceeds max jsize "+std::to_string(std::numeric_limits<jsize>::max()), E_FILE_LINE);
795 }
796 const jsize jarray_size = array_size;
797
798 jmethodID arraylist_add;
799 jobject result = get_new_arraylist(env, jarray_size, &arraylist_add);
800
801 if (jarray_size == 0)
802 {
803 return result;
804 }
805
806 for (jsize i = 0; i < jarray_size; ++i)
807 {
808 jobject object = ctor(env, array[i] /* const U& */);
809 if (!object)
810 {
811 throw jau::RuntimeException("Cannot create instance of class", E_FILE_LINE);
812 }
813 env->CallBooleanMethod(result, arraylist_add, object);
815 }
816 return result;
817 }
818
819 /**@}*/
820
821
822} // namespace jau::jni
823
824#endif /* JAU_HELPER_JNI_HPP_ */
#define E_FILE_LINE
Class template jau::function is a general-purpose static-polymorphic function wrapper.
Pure virtual JavaAnon, hiding Java JNI details from API, to be implemented by JNI module.
~JavaGlobalObj() noexcept override
JavaGlobalObj & operator=(const JavaGlobalObj &o) noexcept=default
JavaGlobalObj(const JNIGlobalRef &obj, jmethodID mNotifyDeleted_) noexcept
static jobject checkAndGetObject(const JavaAnonRef &shref, const char *file, int line)
JavaGlobalObj(JNIGlobalRef &&obj, jmethodID mNotifyDeleted_) noexcept
jobject getObject() const noexcept
static jobject GetObject(const JavaAnonRef &shref) noexcept
static bool isValid(const JavaAnonRef &shref) noexcept
JavaGlobalObj(jobject obj, jmethodID mNotifyDeleted_) noexcept
const JNIGlobalRef & getJavaObject() const noexcept
std::string toString() const noexcept override
JavaGlobalObj(JavaGlobalObj &&o) noexcept=default
static void check(const JavaAnonRef &shref, const char *file, int line)
JavaGlobalObj(const JavaGlobalObj &o) noexcept=default
static JNIGlobalRef GetJavaObject(const JavaAnonRef &shref) noexcept
JNIGlobalRef getJavaObject() noexcept
static jclass GetClass(const JavaAnonRef &shref) noexcept
jclass getClass() const noexcept
JavaGlobalObj & operator=(JavaGlobalObj &&o) noexcept=default
void null_check2() const
Throws an exception if either this instances shared_ptr<T> storage or the managed object reference is...
void null_check1() const
Throws an exception if this instances shared_ptr<T> storage is nullptr.
bool is_null() const noexcept
Returns true if either this instances shared_ptr<T> storage or the managed object reference is nullpt...
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,...
shared_ptr_ref(const std::shared_ptr< T > &ref)
Constructs a new instance, copying the given std::shared_ptr<T>.
T * operator->()
Provides access to pointer of stored T.
shared_ptr_ref(std::shared_ptr< T > &&ref) noexcept
Constructs a new instance, moving the given std::shared_ptr<T>.
const std::shared_ptr< T > & shared_ptr() const
Provides access to const reference of shared_ptr<T>, r-value.
shared_ptr_ref(const shared_ptr_ref &o) noexcept
Copy constructor.
std::shared_ptr< T > * pointer() noexcept
Provides access to the shared_ptr<T> pointer, l-value of storage.
std::shared_ptr< T > * release() noexcept
Release ownership and returns the shared_ptr<T> storage.
std::string toString() const noexcept
shared_ptr_ref(T *ptr)
Constructs a new instance, taking ownership of the given T pointer.
shared_ptr_ref & operator=(shared_ptr_ref &&o) noexcept
Move assignment operator.
T & operator*()
Provides access to reference of stored T.
jlong release_to_jlong() noexcept
Release ownership and return the jlong representation of the shared_ptr<T> storage.
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.
shared_ptr_ref(shared_ptr_ref &&o) noexcept
Move constructor.
shared_ptr_ref() noexcept
Default constructor, nullptr.
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...
shared_ptr_ref & operator=(const shared_ptr_ref &o)
Assignment operator.
shared_ptr_ref & operator=(const std::shared_ptr< T > &o)
Assignment operator.
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
Like std::for_each() of 'algorithm'.
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:55
std::shared_ptr< JavaGlobalObj > JavaGlobalObjRef
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.
jfieldID getField(JNIEnv *env, jobject obj, const char *field_name, const char *field_signature)
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.
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...
jfieldID getInstanceField(JNIEnv *env, jobject obj)
jobject convert_vector_to_jarraylist(JNIEnv *env, T &array, jau::function< jobject(JNIEnv *, const U &)> ctor)
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.
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...
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)
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)
void print_native_caught_exception_fwd2java(const jau::ExceptionBase &e, const char *file, int line)
jobject convert_vector_sharedptr_to_jarraylist(JNIEnv *env, T &array)
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)
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
jobject convert_vector_string_to_jarraylist(JNIEnv *env, const std::vector< std::string > &array)
T * getObjectRef(JNIEnv *env, jobject obj, const char *field_name)
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)
void raise_java_exception(JNIEnv *env, const jau::ExceptionBase &e, const char *file, int line)
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, const bool skipLeading0x=false) noexcept
Produce a lower-case hexadecimal string representation with leading 0x in MSB of the given pointer.
STL namespace.