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?

amigo
  • 343
  • 5
  • 19

1 Answers1

6

From the JNI specification:

A pending exception raised through the JNI (by calling ThrowNew, for example) does not immediately disrupt the native method execution. This is different from how exceptions behave in the Java programming language. When an exception is thrown in the Java programming language, the virtual machine automatically transfers the control flow to the nearest enclosing try/catch statement that matches the exception type. The virtual machine then clears the pending exception and executes the exception handler. In contrast, JNI programmers must explicitly implement the control flow after an exception has occurred.

ignis
  • 8,692
  • 2
  • 23
  • 20
  • 1
    Ok. As I see I have to"must explicitly implement the control flow after an exception has occurred" – amigo Dec 12 '12 at 17:59
  • Ok. As I see I "must explicitly implement the control flow after an exception has occurred". And what is the best way to implement the rest of code after exception has occurred? Do I have to use if-else sequence like ' //code if (condition1) { throwsException1Expr(); //do nothing } else { //code if (condition 2) { throwsException2Expr(); //do nothing } }' or like this: ' //code if (condition1) { throwsException1Expr(); return; } //code if (condition 2) { throwsException2Expr(); return; } }' – amigo Dec 12 '12 at 18:16
  • There's no best way, pick the simplest one. – ignis Dec 12 '12 at 18:25