Android jni/ndk编程五:jni异常处理

Java的编程中,我们经常会遇到各种的异常,也会处理各种的异常。处理异常在java中非常简单,我们通常会使用try-catch-finally来处理,也可以使用throw简单抛出一个异常。那么在jni编程的时候我们又是如何处理异常的呢?

异常处理流程

jni规范已经给我们做好了所有需要做的事情。回想一下处理异常的过程:

  1. 我们首先要在有可能产生异常的地方检测异常
  2. 处理异常 
    是的,我觉得异常的处理就是可以简单的总结为两步,在异常处理中我们通常会打印栈信息等。在jni编程中,异常处理的思路应该也与之类似,过程可用下图表示: 
    这里写图片描述 
    在jni中我么需要手动清除异常。因此,jni中异常的处理应该严格遵循:检查->处理->清除的流程,在图中我把清除也认为是处理的其中一步了。

JNI中异常处理函数

jni.h中有如下相关的函数的定义:

    jint        (*Throw)(JNIEnv*, jthrowable);
    jint        (*ThrowNew)(JNIEnv *, jclass, const char *);
    jthrowable  (*ExceptionOccurred)(JNIEnv*);
    void        (*ExceptionDescribe)(JNIEnv*);
    void        (*ExceptionClear)(JNIEnv*);
    void        (*FatalError)(JNIEnv*, const char*);

此外,还有一个函数和他们没放在一起:

    jboolean    (*ExceptionCheck)(JNIEnv*);

单从名字上我们可以知道用于检测异常的发生的函数有:

  • (ExceptionCheck)(JNIEnv);
  • (ExceptionOccurred)(JNIEnv); 
    用于清理异常的有:
  • (ExceptionClear)(JNIEnv); 
    用于跑出异常的有:
  • (Throw)(JNIEnv, jthrowable);
  • (ThrowNew)(JNIEnv , jclass, const char *);
  • (FatalError)(JNIEnv, const char*); 
    下面对以上函数做一个简单的介绍: 
    1> ExceptionCheck:检查是否发生了异常,若有异常返回JNI_TRUE,否则返回JNI_FALSE 
    2> ExceptionOccurred:检查是否发生了异常,若用异常返回该异常的引用,否则返回NULL 
    3> ExceptionDescribe:打印异常的堆栈信息 
    4> ExceptionClear:清除异常堆栈信息 
    5> ThrowNew:在当前线程触发一个异常,并自定义输出异常信息 
    6> Throw:丢弃一个现有的异常对象,在当前线程触发一个新的异常 
    7> FatalError:致命异常,用于输出一个异常信息,并终止当前VM实例(即退出程序)

测试异常

根据以上总结,我们写如下功能的测试代码: 
native调用java中的方法,java中的方法抛出异常,我们在native中检测异常,检测到后抛出native中的异常,并清理异常。

c代码

void native_catchException(JNIEnv *env, jobject obj)
{
    jthrowable exc;
    jclass cls = (*env)->GetObjectClass(env, obj);
    jmethodID mid =(*env)->GetMethodID(env, cls, "callbackException", "()V"); if (mid == NULL) { return; } (*env)->CallVoidMethod(env, obj, mid); exc = (*env)->ExceptionOccurred(env); if (exc) { jclass newExcCls; (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); newExcCls = (*env)->FindClass(env,"java/lang/IllegalArgumentException"); if (newExcCls == NULL) { /* Unable to find the exception class, give up. */ return; } (*env)->ThrowNew(env, newExcCls, "thrown from C code"); } } static JNINativeMethod gMethods[] = { ... {"exception","()V",(void *)native_catchException}, }; 

代码的其他部分请参看之前的章节。

java代码

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text);
        try { exception(); } catch (Exception e) { System.out.println("In Java:\n\t" + e); } } private native void exception() throws IllegalArgumentException; private void callbackException() throws NullPointerException { throw new NullPointerException("MainActivity.callbackException"); }

输出

09-26 10:58:50.012 23934-23934/com.jinwei.jnitesthello W/System.err: java.lang.NullPointerException: MainActivity.callbackException 09-26 10:58:50.012 23934-23934/com.jinwei.jnitesthello W/System.err: at com.jinwei.jnitesthello.MainActivity.callbackException(MainActivity.java:24) 09-26 10:58:50.012 23934-23934/com.jinwei.jnitesthello W/System.err: at com.jinwei.jnitesthello.MainActivity.exception(Native Method) 09-26 10:58:50.012 23934-23934/com.jinwei.jnitesthello W/System.err: at com.jinwei.jnitesthello.MainActivity.onCreate(MainActivity.java:32) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.Activity.performCreate(Activity.java:6299) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.ActivityThread.-wrap11(ActivityThread.java) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.os.Looper.loop(Looper.java:148) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5417) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at java.lang.reflect.Method.invoke(Native Method) 09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:731) 09-26 

转载于:https://www.cnblogs.com/chenxibobo/p/6895489.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值