简单记录一下
以RuntimeException为例。这是C++的代码,如果使用C的代码的话JNIEnv的使用方式应该为(*env)->FindClass(env, “java/lang/RuntimeException”);
注意是用的"->",同时参数中要加上JNIEnv的结构体指针
void runtime_exception_throw(JNIEnv *env, const char * m) {
if(!env) return;
jclass exception_class = (*env).FindClass("java/lang/RuntimeException");
if(exception_class) {
(*env).ThrowNew(exception_class, (char *)m);
}
(*env).DeleteLocalRef(exception_class);
}
如果想要在抛出异常时进行字符串格式化,可以在调用函数之前先用sprintf格式化一下,或者弄个宏:
#define RUNTIME_EXCETION_THROW(e, format, ...) do { \
char buffer[256]; \
sprintf(buffer, format, ##__VA_ARGS__); \
runtime_exception_throw(e, buffer); \
} while (0)
buffer为256字节,对正常的异常抛出应该是没有问题的,实际上可以减小
使用时直接用RUNTIME_EXCEPTION_THROW来输出即可,如:
RUNTIME_EXCEPTION_THROW(env, "Error code : #%d. Error message : %s", errCode, message);
也可以选择将异常的类名称作为参数进行传入,这样的话,可以更为灵活地使用。
再说几点发现吧:
1.在JNI中抛出异常并不会立刻终止native代码的运行,如果在抛出异常后立即使用(*env).ExceptionClear()清除异常的话,JAVA层也不会收到异常。
2.异常的抛出并非即时的,例如在一个耗时的解码流程前抛出异常,发现在完成解码流程,函数返回后程序才崩溃。