转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119547007
本文出自【赵彦军的博客】
JNI捕获异常
如果 JNI 调用 java 代码,Java 代码发生发生异常,会发生什么情况
举例:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<View>(R.id.sample_text).setOnClickListener {
run()
}
}
external fun run()
/**
* 这个方法会发生异常
*/
fun sum() {
1 / 0
}
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
c++ 代码实现:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
jclass cls = env->GetObjectClass(thiz);
jmethodID jmethodId = env->GetMethodID(cls, "sum", "()V");
env->CallVoidMethod(thiz, jmethodId);
}
app 运行起来,会看到程序崩溃,日志如下:
那么如何在 JNI 中捕获?其实很简单
jthrowable ExceptionOccurred()
举例如下:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
jclass cls = env->GetObjectClass(thiz);
jmethodID jmethodId = env->GetMethodID(cls, "sum", "()V");
env->CallVoidMethod(thiz, jmethodId);
//捕获异常
jthrowable throwable = env->ExceptionOccurred();
if (throwable) {
//如果有异常发生,输出异常信息
env->ExceptionDescribe();
//清除异常信息,app就不会崩溃
env->ExceptionClear();
}
}
JNI抛出异常
在上面的章节中,我们学习了JNI 捕获异常,并且清除了异常信息。但是这样做治标不治本,我们需要的是能够捕获到异常,并且抛出到 Java 层。
jint Throw(jthrowable obj)
举例说明:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
jclass cls = env->GetObjectClass(thiz);
jmethodID jmethodId = env->GetMethodID(cls, "sum", "()V");
env->CallVoidMethod(thiz, jmethodId);
//捕获异常
jthrowable throwable = env->ExceptionOccurred();
if (throwable) {
//抛出异常
env->Throw(throwable);
}
}
Java 代码如下:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<View>(R.id.sample_text).setOnClickListener {
//捕获异常
try {
run()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
external fun run()
/**
* 这个方法会发生异常
*/
fun sum() {
1 / 0
}
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
APP运行起来,我们看看效果:
可以看到我们已经在 Java 代码中捕获到了异常。
除此之外,我们还可以自定义异常,然后抛出,示例如下:
extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_run(JNIEnv *env, jobject thiz) {
jclass cls = env->GetObjectClass(thiz);
jmethodID jmethodId = env->GetMethodID(cls, "sum", "()V");
env->CallVoidMethod(thiz, jmethodId);
//捕获异常
jthrowable throwable = env->ExceptionOccurred();
if (throwable) {
//清除原有的异常
env->ExceptionClear();
//创建自定义异常,并抛出
jclass exception = env->FindClass("java/lang/Exception");
env->ThrowNew(exception, "jni发生异常了");
}
}
看看效果: