JDK1.3.1_04以降またはJDK1.4以降をご使用であれば、java起動時のオプションに次のオプションを指定することにより、実行時のJNIの引数チェック等ができます。
-Xcheck:jni
異常がある場合、次のメッセージが表示されます。
"FATAL ERROR in native method: XXXX"
XXXX部は次のとおりです。メッセージに従って処理を確認してください。
-
"JNI received a class argument that is not a class"
例:char buf[1];
(*env)->AllocObject(env, (jclass)buf); //jclass型の第2引数に違う型を指定
-
"JNI received a null class"
例:(*env)->AllocObject(env, NULL); //jclass型の第2引数にNULLを指定
-
"JNI string operation received a non-string"
例:(*env)->GetStringUTFChars(env, NULL, 0); //jstring型の第2引数にNULLを指定
-
"Non-array passed to JNI array operations"
例:(*env)->GetArrayLength(env, (jarray)(*env)->NewStringUTF(env, "abc"));
//jarray型の第2引数に配列でない型を指定
ただし次の場合は、“-Xcheck:jni”オプションによるメッセージは出力されません。
char buf[1];
(*env)->GetArrayLength(env, (jarray)buf);
-
"Static field ID passed to JNI"
例:jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fid = (*env)->GetFieldID(env, cls, "static_data", "I"); //jfieldID型の第3引数にstaticフィールドを指定
(*env)->GetIntField(env, obj, fid);
-
"Null object passed to JNI"
例:jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fid = (*env)->GetFieldID(env, cls, "instance_data", "I");
(*env)->GetIntField(env, NULL, fid); //object型の第2引数にNULLを指定
instance変数かどうかのチェック時のみに出力されるメッセージです。次の場合は、“-Xcheck:jni”オプションによるメッセージは出力されません。
(*env)->GetObjectClass(env, NULL); //object型の第2引数にNULLを指定
-
"Wrong field ID passed to JNI"
例:(*env)->GetIntField(env, obj, -1); //jfieldID型の第3引数に数値を指定
instance変数かどうかのチェック時のみに出力されるメッセージです。
-
"Non-static field ID passed to JNI"
例:jclass cls = (*env)->GetObjectClass(env, obj);
(*env)->GetStaticIntField(env, cls, -1); //jfieldID型第3引数に数値を指定
ただし次の場合は、“-Xcheck:jni”オプションによるメッセージは出力されません。
jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "instance_data", "I"); //第3引数は、本来staticのフィールド
(*env)->GetStaticIntField(env, cls, fid);
-
"Array element type mismatch in JNI"
例:jintArray intarray = (*env)->NewIntArray(env, 2);
(*env)->GetFloatArrayElements(env, intarray, 0); //floatArray型の第2引数にjintArrayを指定
-
"Object array expected but not received for JNI array operation"
例:jclass cls = (*env)->GetObjectClass(env, obj);
jobjectArray objarray = (*env)->NewObjectArray(env, 1, cls, obj);
(*env)->GetIntArrayElements(env, objarray, 0); //intArray型の第2引数にjobjectArray型を指定
-
"Unknown array object passed to JNI array operations"
-
"Field type (static) mismatch in JNI get/set field operations"
例:jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "static_data", "I");
(*env)->GetStaticFloatField(env, cls, fid); //GetStaticFloatFieldではなくGetStaticIntFieldでなければならない
-
"Static field not found in JNI get/set field operations"
-
"Field type (instance) mismatch in JNI get/set field operations"
例:jclass cls = (*env)->GetObjectClass(env, obj);
jfieldID fid = (*env)->GetFieldID(env, cls, "instance_data", "I");
(*env)->GetFloatField(env, obj, fid); //GetFloatFieldではなくGetIntFieldでなければならない
-
"Instance field not found in JNI get/set field operations"
-
"Wrong static field ID passed to JNI"
例:jclass cls = (*env)->GetObjectClass(env, obj);
jclass cls2 = (*env)->GetObjectClass(env, (*env)->NewStringUTF(env, "abc"));
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "static_data", "I");
(*env)->GetStaticObjectField(env, cls2, fid); //第2引数はcls2ではなくclsでなければならない
-
"Wrong object class or methodID passed to JNI call"
-
"Bad global or local ref passed to JNI"
-
"Using JNIEnv in the wrong thread"
実行しているスレッドのためのものではないJNIEnvを使用したためのエラーです。
Java VMは、JNIインタフェースポインタ(JNIEnv)が参照する領域を、スレッド固有のデータ領域に割り当てることがあります。このため、JNIインタフェースポインタは、カレントスレッドに対してのみ有効です。ネイティブメソッドは、JNIインタフェースポインタを別のスレッドに渡すといった使い方はできません。