5#ifndef WPIUTIL_WPI_JNI_UTIL_H_
6#define WPIUTIL_WPI_JNI_UTIL_H_
54 JClass(JNIEnv* env,
const char* name) {
55 jclass local = env->FindClass(name);
59 m_cls =
static_cast<jclass
>(env->NewGlobalRef(local));
60 env->DeleteLocalRef(local);
65 env->DeleteGlobalRef(
m_cls);
70 explicit operator bool()
const {
return m_cls; }
72 operator jclass()
const {
return m_cls; }
89 m_cls =
static_cast<T
>(env->NewGlobalRef(obj));
94 env->DeleteGlobalRef(
m_cls);
99 explicit operator bool()
const {
return m_cls; }
101 operator T()
const {
return m_cls; }
129 m_env->DeleteLocalRef(m_obj);
132 operator T() {
return m_obj; }
154 jsize
size = env->GetStringLength(
str);
155 const jchar* chars = env->GetStringCritical(
str,
nullptr);
158 env->ReleaseStringCritical(
str, chars);
161 errs() <<
"JStringRef was passed a null pointer at \n"
181template <
typename C,
typename T>
184 operator std::span<const T>()
const {
185 return static_cast<const C*
>(
this)->
array();
199 auto arr =
static_cast<const C*
>(
this)->
array();
203 return {
reinterpret_cast<const char*
>(arr.data()), arr.size()};
206 std::span<const uint8_t>
uarray()
const {
207 auto arr =
static_cast<const C*
>(
this)->
array();
211 return {
reinterpret_cast<const uint8_t*
>(arr.data()), arr.size()};
222 template <
typename U>
223 requires(
sizeof(U) ==
sizeof(jlong) && std::integral<U>)
224 operator std::span<const U>()
const {
225 auto arr =
static_cast<const C*
>(
this)->
array();
229 return {
reinterpret_cast<const U*
>(arr.data()), arr.size()};
239 explicit operator bool()
const {
return this->
m_elements !=
nullptr; }
260 oth.m_jarr =
nullptr;
261 oth.m_elements =
nullptr;
265 this->
m_env = oth.m_env;
266 this->
m_jarr = oth.m_jarr;
267 this->
m_size = oth.m_size;
269 oth.m_jarr =
nullptr;
270 oth.m_elements =
nullptr;
290 :
JArrayRefBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
302#define WPI_JNI_JARRAYREF(T, F) \
303 class J##F##ArrayRef : public detail::JArrayRefBase<T> { \
305 J##F##ArrayRef(JNIEnv* env, jobject bb, int len) \
306 : detail::JArrayRefBase<T>( \
308 static_cast<T*>(bb ? env->GetDirectBufferAddress(bb) : nullptr), \
311 errs() << "JArrayRef was passed a null pointer at \n" \
312 << GetJavaStackTrace(env); \
315 J##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
316 : detail::JArrayRefBase<T>(env, jarr, len) { \
318 m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
320 errs() << "JArrayRef was passed a null pointer at \n" \
321 << GetJavaStackTrace(env); \
324 J##F##ArrayRef(JNIEnv* env, T##Array jarr) \
325 : detail::JArrayRefBase<T>(env, jarr) { \
327 m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
329 errs() << "JArrayRef was passed a null pointer at \n" \
330 << GetJavaStackTrace(env); \
333 ~J##F##ArrayRef() { \
334 if (m_jarr && m_elements) { \
335 m_env->Release##F##ArrayElements(static_cast<T##Array>(m_jarr), \
336 m_elements, JNI_ABORT); \
341 class CriticalJ##F##ArrayRef : public detail::JArrayRefBase<T> { \
343 CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
344 : detail::JArrayRefBase<T>(env, jarr, len) { \
347 static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
349 errs() << "JArrayRef was passed a null pointer at \n" \
350 << GetJavaStackTrace(env); \
353 CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr) \
354 : detail::JArrayRefBase<T>(env, jarr) { \
357 static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
359 errs() << "JArrayRef was passed a null pointer at \n" \
360 << GetJavaStackTrace(env); \
363 ~CriticalJ##F##ArrayRef() { \
364 if (m_jarr && m_elements) { \
365 m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, JNI_ABORT); \
378#undef WPI_JNI_JARRAYREF
393 return env->NewString(chars.
begin(), chars.
size());
401 static jintArray
ToJava(JNIEnv* env, std::span<const T> arr) {
402 if constexpr (
sizeof(T) ==
sizeof(jint) && std::integral<T>) {
404 jintArray jarr = env->NewIntArray(arr.size());
408 env->SetIntArrayRegion(jarr, 0, arr.size(),
409 reinterpret_cast<const jint*
>(arr.data()));
416 jintArray jarr = env->NewIntArray(arr.size());
421 static_cast<jint*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
425 for (
size_t i = 0; i < arr.size(); ++i) {
426 elements[i] =
static_cast<jint
>(arr[i]);
428 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
454inline jintArray
MakeJIntArray(JNIEnv* env, std::span<T> arr) {
493 jbyteArray jarr = env->NewByteArray(str.size());
497 env->SetByteArrayRegion(jarr, 0, str.size(),
498 reinterpret_cast<const jbyte*
>(str.data()));
509 jbooleanArray jarr = env->NewBooleanArray(arr.size());
514 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
518 for (
size_t i = 0; i < arr.size(); ++i) {
519 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
521 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
532 jbooleanArray jarr = env->NewBooleanArray(arr.size());
537 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
541 for (
size_t i = 0; i < arr.size(); ++i) {
542 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
544 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
550#define WPI_JNI_MAKEJARRAY(T, F) \
551 inline T##Array MakeJ##F##Array(JNIEnv* env, std::span<const T> arr) { \
552 T##Array jarr = env->New##F##Array(arr.size()); \
556 env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data()); \
566#undef WPI_JNI_MAKEJARRAY
569 requires(
sizeof(
typename T::value_type) ==
sizeof(jlong) &&
570 std::integral<typename T::value_type>)
572 jlongArray jarr = env->NewLongArray(arr.size());
576 env->SetLongArrayRegion(jarr, 0, arr.size(),
577 reinterpret_cast<const jlong*
>(arr.data()));
588 std::span<const std::string> arr) {
589 static JClass stringCls{env,
"java/lang/String"};
593 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
597 for (
size_t i = 0; i < arr.size(); ++i) {
599 env->SetObjectArrayElement(jarr, i, elem.obj());
611 std::span<std::string_view> arr) {
612 static JClass stringCls{env,
"java/lang/String"};
616 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
620 for (
size_t i = 0; i < arr.size(); ++i) {
622 env->SetObjectArrayElement(jarr, i, elem.obj());
647 void Main()
override;
658 void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
660 template <
typename... Args>
661 void Send(Args&&... args);
666 auto thr = this->GetThread();
672 env->DeleteGlobalRef(thr->m_func);
675 thr->m_func = env->NewGlobalRef(func);
680template <
typename... Args>
682 auto thr = this->GetThread();
686 thr->m_queue.emplace(std::forward<Args>(args)...);
687 thr->m_cond.notify_one();
693 JavaVMAttachArgs args;
694 args.version = JNI_VERSION_1_2;
695 args.name =
const_cast<char*
>(T::GetName());
696 args.group =
nullptr;
697 jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
698 reinterpret_cast<void**
>(&env), &args);
703 std::unique_lock lock(m_mutex);
705 m_cond.wait(lock, [&] {
return !(m_active && m_queue.empty()); });
709 while (!m_queue.empty()) {
713 auto item = std::move(m_queue.front());
718 item.CallJava(env, func, mid);
719 if (env->ExceptionCheck()) {
720 env->ExceptionDescribe();
721 env->ExceptionClear();
727 JavaVM* jvm = T::GetJVM();
729 jvm->DetachCurrentThread();
744 static JClass throwableCls(env,
"java/lang/Throwable");
748 static jmethodID constructorId =
nullptr;
749 if (!constructorId) {
750 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
752 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
757 static jmethodID getStackTraceId =
nullptr;
758 if (!getStackTraceId) {
759 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
760 "()[Ljava/lang/StackTraceElement;");
765 env,
static_cast<jobjectArray
>(
766 env->CallObjectMethod(throwable, getStackTraceId)));
773 jsize stackTraceLength = env->GetArrayLength(stackTrace);
776 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
777 if (!stackTraceElementCls) {
780 static jmethodID toStringId =
nullptr;
782 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
783 "()Ljava/lang/String;");
786 bool foundFirst =
false;
789 for (jsize i = 0; i < stackTraceLength; i++) {
792 env, env->GetObjectArrayElement(stackTrace, i));
796 env,
static_cast<jstring
>(
797 env->CallObjectMethod(curStackTraceElement, toStringId)));
799 if (!stackElementString) {
811 oss <<
"\tat " << elem <<
'\n';
820 static JClass throwableCls(env,
"java/lang/Throwable");
824 static jmethodID constructorId =
nullptr;
825 if (!constructorId) {
826 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
828 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
833 static jmethodID getStackTraceId =
nullptr;
834 if (!getStackTraceId) {
835 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
836 "()[Ljava/lang/StackTraceElement;");
841 env,
static_cast<jobjectArray
>(
842 env->CallObjectMethod(throwable, getStackTraceId)));
849 jsize stackTraceLength = env->GetArrayLength(stackTrace);
852 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
853 if (!stackTraceElementCls) {
856 static jmethodID toStringId =
nullptr;
858 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
859 "()Ljava/lang/String;");
862 bool haveLoc =
false;
865 for (jsize i = 0; i < stackTraceLength; i++) {
868 env, env->GetObjectArrayElement(stackTrace, i));
872 env,
static_cast<jstring
>(
873 env->CallObjectMethod(curStackTraceElement, toStringId)));
875 if (!stackElementString) {
888 }
else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
912 env->GetMethodID(
m_cls,
"<init>",
"(Ljava/lang/String;)V");
916 void Throw(JNIEnv* env, jstring msg) {
918 env->Throw(
static_cast<jthrowable
>(
exception));
925 explicit operator bool()
const {
return m_constructor; }
928 jmethodID m_constructor =
nullptr;
This file defines the SmallString class.
This file defines the SmallVector class.
you may not use this file except in compliance with the License You may obtain a copy of the License at software distributed under the License is distributed on an AS IS WITHOUT WARRANTIES OR CONDITIONS OF ANY either express or implied See the License for the specific language governing permissions and limitations under the License LLVM Exceptions to the Apache License As an exception
Definition: ThirdPartyNotices.txt:289
Definition: SafeThread.h:33
Definition: SafeThread.h:124
std::string_view str() const
Explicit conversion to std::string_view.
Definition: SmallString.h:181
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1186
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:557
void pop_back()
Definition: SmallVector.h:415
void push_back(const T &Elt)
Definition: SmallVector.h:403
size_t size() const
Definition: SmallVector.h:78
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:271
iterator begin()
Definition: SmallVector.h:252
This class is a wrapper around std::array that does compile time size checking.
Definition: array.h:26
void SetJoinAtExit(bool joinAtExit)
Definition: SafeThread.h:106
Definition: jni_util.h:655
JCallbackManager()
Definition: jni_util.h:657
void SetFunc(JNIEnv *env, jobject func, jmethodID mid)
Definition: jni_util.h:665
void Send(Args &&... args)
Definition: jni_util.h:681
Generic callback thread implementation.
Definition: jni_util.h:645
jmethodID m_mid
Definition: jni_util.h:651
jobject m_func
Definition: jni_util.h:650
std::queue< T > m_queue
Definition: jni_util.h:649
void Main() override
Definition: jni_util.h:691
Finds a class and keeps it as a global reference.
Definition: jni_util.h:50
JClass(JNIEnv *env, const char *name)
Definition: jni_util.h:54
jclass m_cls
Definition: jni_util.h:75
void free(JNIEnv *env)
Definition: jni_util.h:63
Finds an exception class and keep it as a global reference.
Definition: jni_util.h:906
void Throw(JNIEnv *env, std::string_view msg)
Definition: jni_util.h:921
JException(JNIEnv *env, const char *name)
Definition: jni_util.h:909
void Throw(JNIEnv *env, jstring msg)
Definition: jni_util.h:916
Definition: jni_util.h:84
JGlobal(JNIEnv *env, T obj)
Definition: jni_util.h:88
void free(JNIEnv *env)
Definition: jni_util.h:92
T m_cls
Definition: jni_util.h:104
Container class for cleaning up Java local references.
Definition: jni_util.h:113
JLocal & operator=(const JLocal &)=delete
~JLocal()
Definition: jni_util.h:127
JLocal(JLocal &&oth)
Definition: jni_util.h:117
JLocal & operator=(JLocal &&oth)
Definition: jni_util.h:121
T obj()
Definition: jni_util.h:133
JLocal(JNIEnv *env, T obj)
Definition: jni_util.h:115
JLocal(const JLocal &)=delete
Definition: jni_util.h:734
static JSingletonCallbackManager< T > & GetInstance()
Definition: jni_util.h:736
Java string (jstring) reference.
Definition: jni_util.h:150
std::string_view str() const
Definition: jni_util.h:170
const char * c_str() const
Definition: jni_util.h:171
size_t size() const
Definition: jni_util.h:172
JStringRef(JNIEnv *env, jstring str)
Definition: jni_util.h:152
Base class for J*ArrayRef and CriticalJ*ArrayRef.
Definition: jni_util.h:237
JArrayRefBase(JNIEnv *env, jarray jarr)
Definition: jni_util.h:289
size_t m_size
Definition: jni_util.h:294
size_t size() const
Definition: jni_util.h:248
std::span< const T > array() const
Definition: jni_util.h:241
JArrayRefBase & operator=(const JArrayRefBase &)=delete
T & operator[](size_t i)
Definition: jni_util.h:249
T * m_elements
Definition: jni_util.h:295
JArrayRefBase(JNIEnv *env, T *elements, size_t size)
Definition: jni_util.h:275
JArrayRefBase & operator=(JArrayRefBase &&oth)
Definition: jni_util.h:264
JArrayRefBase(JNIEnv *env, jarray jarr, size_t size)
Definition: jni_util.h:282
JNIEnv * m_env
Definition: jni_util.h:292
jarray m_jarr
Definition: jni_util.h:293
const T & operator[](size_t i) const
Definition: jni_util.h:250
JArrayRefBase(const JArrayRefBase &)=delete
JArrayRefBase(JArrayRefBase &&oth)
Definition: jni_util.h:255
std::string_view str() const
Definition: jni_util.h:198
std::span< const uint8_t > uarray() const
Definition: jni_util.h:206
Definition: jni_util.h:182
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:554
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:572
basic_string_view< char > string_view
Definition: core.h:520
#define WPI_JNI_MAKEJARRAY(T, F)
Definition: jni_util.h:550
#define WPI_JNI_JARRAYREF(T, F)
Definition: jni_util.h:302
::uint8_t uint8_t
Definition: Meta.h:52
Definition: format-inl.h:32
Java Native Interface (JNI) utility functions.
Definition: jni_util.h:27
jlongArray MakeJLongArray(JNIEnv *env, const T &arr)
Definition: jni_util.h:571
jintArray MakeJIntArray(JNIEnv *env, std::span< const T > arr)
Convert a span to a jintArray.
Definition: jni_util.h:443
jstring MakeJString(JNIEnv *env, std::string_view str)
Convert a UTF8 string into a jstring.
Definition: jni_util.h:390
std::string GetJavaStackTrace(JNIEnv *env, std::string *func=nullptr, std::string_view excludeFuncPrefix={})
Gets a Java stack trace.
Definition: jni_util.h:817
jbooleanArray MakeJBooleanArray(JNIEnv *env, std::span< const int > arr)
Convert an array of integers into a jbooleanArray.
Definition: jni_util.h:508
jobjectArray MakeJStringArray(JNIEnv *env, std::span< const std::string > arr)
Convert an array of std::string into a jarray of jstring.
Definition: jni_util.h:587
jbyteArray MakeJByteArray(JNIEnv *env, std::span< const uint8_t > str)
Convert a span into a jbyteArray.
Definition: jni_util.h:492
bool convertUTF8ToUTF16String(std::string_view SrcUTF8, SmallVectorImpl< UTF16 > &DstUTF16)
Converts a UTF-8 string into a UTF-16 string with native endianness.
bool Boolean
Definition: ConvertUTF.h:115
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool convertUTF16ToUTF8String(std::span< const char > SrcBytes, SmallVectorImpl< char > &Out)
Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
constexpr bool starts_with(std::string_view str, std::string_view prefix) noexcept
Checks if str starts with the given prefix.
Definition: StringExtras.h:232
Definition: jni_util.h:78
const char * name
Definition: jni_util.h:79
JClass * cls
Definition: jni_util.h:80
Definition: jni_util.h:931
JException * cls
Definition: jni_util.h:933
const char * name
Definition: jni_util.h:932
Definition: jni_util.h:400
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition: jni_util.h:401