4

I have the code on JNI level. And it can throws exceptions. The code is:

#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 function creates an object of the custom Information class. Each time I set the class field, there is a check if "fid" is no NULL. I read about JNI exceptions that those are pending exceptions. I figured out that first exception that will be thrown move the code flow to Java level (not JNI level). But what about the rest code after exception in the JNI level. As I understand it will be executed. Is it possible that after first exception the second, third, etc. exceptions will be thrown? Should I return NULL or something after throwing exception in order the rest code in JNI level will not be executed?

4

1 に答える 1

6

JNI仕様から:

JNI を介して (たとえば、ThrowNew を呼び出すことによって) 保留中の例外が発生しても、ネイティブ メソッドの実行がすぐに中断されるわけではありません。これは、Java プログラミング言語での例外の動作とは異なります。Java プログラミング言語で例外がスローされると、仮想マシンは制御フローを、例外の種類に一致する最も近くにある外側の try/catch ステートメントに自動的に転送します。その後、仮想マシンは保留中の例外をクリアし、例外ハンドラーを実行します。対照的に、JNI プログラマーは、例外が発生した後に制御フローを明示的に実装する必要があります。

于 2012-12-12T17:51:31.007 に答える