Android jni/ndk編程五:jni異常處理

來源:互聯網
上載者:User

標籤:sso   message   返回   string   class   exce   ack   roc   地方   

在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.callbackException09-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 10:58:50.013 23934-23934/com.jinwei.jnitesthello W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello I/System.out: In Java:09-26 10:58:50.013 23934-23934/com.jinwei.jnitesthello I/System.out:    java.lang.IllegalArgumentException: thrown from C code

從輸出中我們看到c代碼中使用:(*env)->ThrowNew(env, newExcCls, “thrown from C code”);這行代碼跑出了異常。然後java中的異常處理函數列印了棧的資訊。

工具函數

JNI中拋異常很經典:找異常類,調用ThrowNew拋出之;所以,可以寫一個工具函數。

voidJNU_ThrowByName(JNIEnv *env, const char *name, const char *msg){    jclass cls = (*env)->FindClass(env, name);    /* if cls is NULL, an exception has already been thrown */    if (cls != NULL) {        (*env)->ThrowNew(env, cls, msg);    }    /* free the local ref */    (*env)->DeleteLocalRef(env, cls);}

Android jni/ndk編程五:jni異常處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.