Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions native/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,54 @@ throwByName(JNIEnv *env, const char *name, const char *msg)
{
jclass cls;

jthrowable thrown = (*env)->ExceptionOccurred(env);
(*env)->ExceptionClear(env);

cls = (*env)->FindClass(env, name);

if (cls != NULL) { /* Otherwise an exception has already been thrown */
if (thrown != NULL) {
/* Attach thrown exception if possible. */
/* do_throw_clean is an exit path that will delete 'thrown' if we can't do that. */
jmethodID init = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
if (init == NULL) {
goto do_throw_clean;
}
jmethodID initCause = (*env)->GetMethodID(env, cls, "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
if (initCause == NULL) {
goto do_throw_clean;
}
jobject str = (*env)->NewStringUTF(env, msg);
if (str == NULL) {
goto do_throw_clean;
}
jthrowable t = (jthrowable) (*env)->NewObject(env, cls, init, str);
(*env)->DeleteLocalRef(env, str);
if (t == NULL) {
goto do_throw_clean;
}
jobject ret = (*env)->CallObjectMethod(env, t, initCause, thrown);
if (ret == NULL) {
goto do_throw_clean;
}
(*env)->DeleteLocalRef(env, ret);
(*env)->Throw(env, t);
goto clean_cls;
} else {
goto do_throw;
}
/* Deletes thrown exception reference and clears the exception. */
do_throw_clean:
(*env)->DeleteLocalRef(env, thrown);
(*env)->ExceptionClear(env);
do_throw:
(*env)->ThrowNew(env, cls, msg);

clean_cls:
/* It's a good practice to clean up the local references. */
(*env)->DeleteLocalRef(env, cls);
} else if (thrown != NULL) {
(*env)->DeleteLocalRef(env, thrown);
}
Comment on lines 426 to 469
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the cases are to complex and can be simplified to:

Suggested change
if (cls != NULL) { /* Otherwise an exception has already been thrown */
if (thrown != NULL) {
/* Attach thrown exception if possible. */
/* do_throw_clean is an exit path that will delete 'thrown' if we can't do that. */
jmethodID init = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
if (init == NULL) {
goto do_throw_clean;
}
jmethodID initCause = (*env)->GetMethodID(env, cls, "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
if (initCause == NULL) {
goto do_throw_clean;
}
jobject str = (*env)->NewStringUTF(env, msg);
if (str == NULL) {
goto do_throw_clean;
}
jthrowable t = (jthrowable) (*env)->NewObject(env, cls, init, str);
(*env)->DeleteLocalRef(env, str);
if (t == NULL) {
goto do_throw_clean;
}
jobject ret = (*env)->CallObjectMethod(env, t, initCause, thrown);
if (ret == NULL) {
goto do_throw_clean;
}
(*env)->DeleteLocalRef(env, ret);
(*env)->Throw(env, t);
goto clean_cls;
} else {
goto do_throw;
}
/* Deletes thrown exception reference and clears the exception. */
do_throw_clean:
(*env)->DeleteLocalRef(env, thrown);
(*env)->ExceptionClear(env);
do_throw:
(*env)->ThrowNew(env, cls, msg);
clean_cls:
/* It's a good practice to clean up the local references. */
(*env)->DeleteLocalRef(env, cls);
} else if (thrown != NULL) {
(*env)->DeleteLocalRef(env, thrown);
}
if (cls != NULL) { /* Otherwise an exception has already been thrown */
jthrowable t = NULL;
jmethodID init = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
jobject str = (*env)->NewStringUTF(env, msg);
if (init != NULL && str != NULL) {
t = (jthrowable) (*env)->NewObject(env, cls, init, str);
}
if (str != NULL) {
(*env)->DeleteLocalRef(env, str);
}
if (thrown != NULL && t != NULL) {
jmethodID initCause = (*env)->GetMethodID(env, cls, "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
/* Attach thrown exception if possible. */
jobject ret = (*env)->CallObjectMethod(env, t, initCause, thrown);
(*env)->DeleteLocalRef(env, ret);
}
(*env)->Throw(env, t);
(*env)->DeleteLocalRef(env, cls);
}
if (thrown != NULL) {
(*env)->DeleteLocalRef(env, thrown);
}

}

Expand Down