2012-12-12 80 views
3

我有JNI級別的代碼。它可以拋出異常。代碼是:Java中使用JNI的代碼流程

#include "JavaGlueClass.h" 
#include <stdio.h>   
#include <windows.h> 
#include <string.h> 

jint throwNoClassDefError(JNIEnv *env, const char *message) 
{ 
    jclass exClass; 
    char *className = (char *) "java/lang/NoClassDefFoundError" ; 

    exClass = env->FindClass(className); 

    if (exClass != NULL) { 
     return env->ThrowNew(exClass, message); 
    } 

    //free the local ref 
    env->DeleteLocalRef(exClass); 

} 

void throwGetFieldIDException(JNIEnv *env) 
{ 
    const char *className = "GetFieldIDException"; 
    jclass exClass = env->FindClass(className); 
    if (exClass == NULL) { 
     throwNoClassDefError(env, className); 
    } else { 
     env->ThrowNew(exClass, "GetFieldIDException message"); 
    } 
    env->DeleteLocalRef(exClass); 
    printf("printprint"); 
} 




JNIEXPORT jobject JNICALL Java_JavaGlueClass_test(JNIEnv *env, jobject obj) 
{ 
    jmethodID constructor; 
    jobject object; 
    jclass clazz; 
    jfieldID fid; 
    jstring stringField; 

    clazz = env->FindClass("Information"); 
    if (clazz == 0) { 
     printf("error while finding class"); 
     throwNoClassDefError(env, "no such class"); 
    } else {     
     //create object throuht constructor 
     constructor = env->GetMethodID(clazz, "<init>", "()V"); 
     object = env->NewObject(clazz, constructor);  

     // set private value1 field 
     stringField = env->NewStringUTF("str1"); 
     //fid = env->GetFieldID(clazz,"value1","Ljava/lang/String;"); 
     fid = NULL; 
     if (fid == NULL) { 
      throwGetFieldIDException(env, "error with value1 field."); 
      //return NULL; 
     } 

     env->SetObjectField(object, fid, stringField); 

     //set private value2 field 
     fid = env->GetFieldID(clazz,"value2","I"); 
     if (fid == NULL) { 
      throwGetFieldIDException(env, "error with value1 field."); 
      //return NULL; 
     } 
     env->SetIntField(object, fid, 1); 

     // set private value3 field 
     stringField = env->NewStringUTF("str2"); 
     fid = env->GetFieldID(clazz,"value3","Ljava/lang/String;"); 
     if (fid == NULL) { 
      throwGetFieldIDException(env, "error with value1 field."); 
      //return NULL; 
     } 
     env->SetObjectField(object, fid, stringField); 

     //set private value4 field 
     fid = env->GetFieldID(clazz,"value4","I"); 
     if (fid == NULL) { 
      throwGetFieldIDException(env, "error with value1 field."); 
      //return NULL; 
     } 
     env->SetIntField(object, fid, 2); 

     printf("end of cpp function");    
     return object; 
    } 

} 

Java_JavaGlueClass_test函數創建自定義信息類的對象。每次我設置類字段時,都會檢查「fid」是否爲NULL。 我讀了關於那些是未決異常的JNI異常。我發現將拋出的第一個異常會將代碼流移到Java級別(而不是JNI級別)。但是在JNI級別的異常之後的其餘代碼呢?據我瞭解,它將被執行。 第一個異常之後是否有可能拋出第二,第三等異常?我應該在拋出異常之後返回NULL或其他什麼,以便JNI級別的其餘代碼不會被執行?

回答

6

the JNI specification

阿通過JNI凸起(通過調用ThrowNew,例如)現行異常不會立即破壞天然方法執行。這與Java編程語言中異常的行爲方式不同。當使用Java編程語言拋出異常時,虛擬機會自動將控制流傳輸到與異常類型匹配的最近的封閉try/catch語句。虛擬機然後清除待處理的異常並執行異常處理程序。相比之下,JNI程序員必須在異常發生後明確實現控制流程。

+1

好的。正如我所看到的,我必須「在異常發生後必須明確實施控制流程」 –

+0

好的。正如我所看到的,「在異常發生後必須明確地實施控制流程」。發生異常後實現其餘代碼的最佳方式是什麼?我是否必須使用if-else序列,如 ' //代碼 if(condition1){ throwsException1Expr(); //什麼都不做 } else { //代碼 if(條件2){ throwsException2Expr(); //什麼也不做 } } ' 或這樣的: ' //代碼 如果(條件1){ throwsException1Expr(); return; } //代碼 if(條件2){ throwsException2Expr(); return; } }' –

+0

沒有最好的方法,選擇最簡單的一個。 – ignis