-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
exception handling, overloading, global scope (#7)
* add try catch to jni * bug fix for exception handler * make get operator return nullable value * add ability to do things in global scope to get away from memory management * bug fix and more unit tests * add comments * add support for overloading methods * optimize thread to avoid deadlock * add global memory table and unit tests for it * handle null property in json object --------- Co-authored-by: Wenxi Zeng <wzeng@twilio.com>
- Loading branch information
1 parent
67d1932
commit 16db24a
Showing
11 changed files
with
1,026 additions
and
605 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,29 @@ | ||
#include <stdio.h> | ||
#include <string> | ||
#include <iostream> | ||
|
||
#include "java_helper.h" | ||
|
||
#define MAX_MSG_SIZE 1024 | ||
|
||
jint throw_exception(JNIEnv *env, const char *exception_name, const char *message, ...) { | ||
char formatted_message[MAX_MSG_SIZE]; | ||
va_list va_args; | ||
va_start(va_args, message); | ||
vsnprintf(formatted_message, MAX_MSG_SIZE, message, va_args); | ||
va_end(va_args); | ||
void swallow_cpp_exception_and_throw_java(JNIEnv * env) { | ||
try { | ||
throw; | ||
} catch(const ThrownJavaException&) { | ||
//already reported to Java, ignore | ||
} catch(const std::bad_alloc& rhs) { | ||
//translate OOM C++ exception to a Java exception | ||
NewJavaException(env, "java/lang/OutOfMemoryError", rhs.what()); | ||
} catch(const std::ios_base::failure& rhs) { //sample translation | ||
//translate IO C++ exception to a Java exception | ||
NewJavaException(env, "java/io/IOException", rhs.what()); | ||
|
||
jclass exception_class = env->FindClass(exception_name); | ||
if (exception_class == NULL) { | ||
return -1; | ||
} | ||
//TRANSLATE ANY OTHER C++ EXCEPTIONS TO JAVA EXCEPTIONS HERE | ||
|
||
return env->ThrowNew(exception_class, formatted_message); | ||
} | ||
} catch(const std::exception& e) { | ||
//translate unknown C++ exception to a Java exception | ||
NewJavaException(env, "java/lang/Error", e.what()); | ||
} catch(...) { | ||
//translate unknown C++ exception to a Java exception | ||
NewJavaException(env, "java/lang/Error", "Unknown exception type"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,50 @@ | ||
// | ||
// Created by Wenxi Zeng on 3/1/24. | ||
// See the original post here: https://stackoverflow.com/a/12014833/8296631 | ||
// | ||
|
||
#ifndef SUBSTRATA_KOTLIN_JAVA_HELPER_H | ||
#define SUBSTRATA_KOTLIN_JAVA_HELPER_H | ||
|
||
#include <jni.h> | ||
#include <string> | ||
#include <stdexcept> | ||
|
||
#define CLASS_NAME_ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException" | ||
|
||
#define THROW_EXCEPTION(ENV, EXCEPTION_NAME, ...) \ | ||
do { \ | ||
throw_exception((ENV), (EXCEPTION_NAME), __VA_ARGS__); \ | ||
return; \ | ||
} while (0) | ||
#define THROW_EXCEPTION_RET(ENV, EXCEPTION_NAME, ...) \ | ||
do { \ | ||
throw_exception((ENV), (EXCEPTION_NAME), __VA_ARGS__); \ | ||
return 0; \ | ||
} while (0) | ||
#define MSG_OOM "Out of memory" | ||
#define MSG_NULL_JS_RUNTIME "Null JSRuntime" | ||
#define MSG_NULL_JS_CONTEXT "Null JSContext" | ||
#define MSG_NULL_JS_VALUE "Null JSValue" | ||
#define THROW_ILLEGAL_STATE_EXCEPTION(ENV, ...) \ | ||
THROW_EXCEPTION(ENV, CLASS_NAME_ILLEGAL_STATE_EXCEPTION, __VA_ARGS__) | ||
#define THROW_ILLEGAL_STATE_EXCEPTION_RET(ENV, ...) \ | ||
THROW_EXCEPTION_RET(ENV, CLASS_NAME_ILLEGAL_STATE_EXCEPTION, __VA_ARGS__) | ||
#define CHECK_NULL(ENV, POINTER, MESSAGE) \ | ||
do { \ | ||
if ((POINTER) == NULL) { \ | ||
THROW_ILLEGAL_STATE_EXCEPTION((ENV), (MESSAGE)); \ | ||
} \ | ||
} while (0) | ||
#define CHECK_NULL_RET(ENV, POINTER, MESSAGE) \ | ||
do { \ | ||
if ((POINTER) == NULL) { \ | ||
THROW_ILLEGAL_STATE_EXCEPTION_RET((ENV), (MESSAGE)); \ | ||
} \ | ||
} while (0) | ||
|
||
#define MAX_MSG_SIZE 1024 | ||
|
||
jint throw_exception(JNIEnv *env, const char *exception_name, const char *message, ...); | ||
#define CLASS_NAME_ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException" | ||
|
||
struct ThrownJavaException : std::exception { | ||
ThrownJavaException(const std::string& message) : m_message(message) {} | ||
ThrownJavaException() : m_message("") {} | ||
|
||
// Override the what() method to provide a description of the exception | ||
const char* what() const noexcept override { | ||
return m_message.c_str(); | ||
} | ||
|
||
private: | ||
std::string m_message; | ||
}; | ||
|
||
//used to throw a new Java exception. use full paths like: | ||
//"java/lang/NoSuchFieldException" | ||
//"java/lang/NullPointerException" | ||
//"java/security/InvalidParameterException" | ||
struct NewJavaException : public ThrownJavaException{ | ||
NewJavaException(JNIEnv * env, const char* type, const char* message="") | ||
:ThrownJavaException(type+std::string(" ")+message) | ||
{ | ||
jclass newExcCls = env->FindClass(type); | ||
if (newExcCls != NULL) | ||
env->ThrowNew(newExcCls, message); | ||
//if it is null, a NoClassDefFoundError was already thrown | ||
} | ||
}; | ||
|
||
inline void assert_no_exception(JNIEnv * env) { | ||
if (env->ExceptionCheck()==JNI_TRUE) | ||
throw ThrownJavaException("assert_no_exception"); | ||
} | ||
|
||
void swallow_cpp_exception_and_throw_java(JNIEnv * env); | ||
|
||
#endif //SUBSTRATA_KOTLIN_JAVA_HELPER_H |
Oops, something went wrong.