JNI 程序中的异常分为以下几种:
- Native 程序原生异常,一般通过函数返回值和 linux 信号处理, C++ 中也有 try catch 机制解决异常,不是本文重点
- JNIEnv 内部函数抛出的异常,一般通过返回值判断,发现异常直接 return, jvm 会给将异常传递给 Java 层
- Native 回调 Java 层方法,被回调的方法抛出异常,JNI 提供了特定的 API 来处理这类异常
1. JNIEnv 内部函数抛出的异常
很多 JNIEnv 中的函数都会抛出异常,处理方法大体上是一致的:
- 返回值与特殊值(一般是 NULL)比较,知晓函数是否发生异常
- 如果发生异常立即 return
- jvm 会将异常抛给 java 层,我们可以在 java 层通过 try catch 机制捕获异常
接着我们来看一个例子:
Java 层:
public native void exceptionTest();
//调用
try {
exceptionTest();
} catch (Exception e) {
e.printStackTrace();
}
Native 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_exceptionTest(JNIEnv *env, jobject thiz) {
//查找的类不存在,返回 NULL;
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/xxx");
if (clazz == NULL) {
return; //return 后,jvm 会向 java 层抛出 ClassNotFoundException
}
}
执行后的 log:
java.lang.ClassNotFoundException: Didn't find class "com.yuandaima.myjnidemo.xxx"
说明,java 层捕获到了异常
2. Native 回调 Java 层方法,被回调的方法抛出异常
Native 回调 Java 层方法,被回调的方法抛出异常。这样情况下一般有两种解决办法:
- Java 层 Try catch 本地方法,这是比较推荐的办法。
- Native 层处理异常,异常处理如果和 native 层相关,可以采用这种方式
2.1 Java 层 Try catch 本地方法
Java 层:
//执行这个方法会抛出异常
private static int exceptionMethod() {
return 20 / 0;
}
//native 方法,在 native 中,会调用到 exceptionMethod() 方法
public native void exceptionTest();
//Java 层调用
try {
exceptionTest();
} catch (Exception e) {
//这里处理异常
//一般是打 log 和弹 toast 通知用户
e.printStackTrace();
}
Native 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_exceptionTest(JNIEnv *env, jobject thiz) {
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/TestJavaClass");
if (clazz == NULL) {
return;
}
//调用 java 层会抛出异常的方法
jmethodID static_method_id = env->GetStaticMethodID(clazz, "exceptionMethod", "()I");
if (NULL == static_method_id) {
return;
}
//直接调用,发生 ArithmeticException 异常,传回 Java 层
env->CallStaticIntMethod(clazz, static_method_id);
env->DeleteLocalRef(clazz);
}
2.2 Native 层处理异常
有的异常需要在 Native 处理,这里又分为两类:
- 异常在 Native 层就处理完了
- 异常在 Native 层处理了,还需要返回给 Java 层,Java 层继续处理
接着我们看下示例:
Java 层:
//执行这个方法会抛出异常
private static int exceptionMethod() {
return 20 / 0;
}
//native 方法,在 native 中,会调用到 exceptionMethod() 方法
public native void exceptionTest();
//Java 层调用
try {
exceptionTest();
} catch (Exception e) {
//这里处理异常
//一般是打 log 和弹 toast 通知用户
e.printStackTrace();
}
Native 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_exceptionTest(JNIEnv *env, jobject thiz) {
jthrowable mThrowable;
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/TestJavaClass");
if (clazz == NULL) {
return;
}
jmethodID static_method_id = env->GetStaticMethodID(clazz, "exceptionMethod", "()I");
if (NULL == static_method_id) {
return;
}
env->CallStaticIntMethod(clazz, static_method_id);
//检测是否有异常发生
if (env->ExceptionCheck()) {
//获取到异常对象
mThrowable = env->ExceptionOccurred();
//这里就可以根据实际情况处理异常了
//.......
//打印异常信息堆栈
env->ExceptionDescribe();
//清除异常信息
//如果,异常还需要 Java 层处理,可以不调用 ExceptionClear,让异常传递给 Java 层
env->ExceptionClear();
//如果调用了 ExceptionClear 后,异常还需要 Java 层处理,我们可以抛出一个新的异常给 Java 层
jclass clazz_exception = env->FindClass("java/lang/Exception");
env->ThrowNew(clazz_exception, "JNI抛出的异常!");
env->DeleteLocalRef(clazz_exception);
}
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(mThrowable);
}
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20406,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20406,转载请注明出处。
评论0