Java以外の言語と連携する場合、Java Native Interface(JNI)を使用します。
しかし、JNIの使用方法を誤ると、Javaプロセスの終了(異常終了)などの原因となります。
このとき、図1のオプションを指定することにより、JNI処理で異常が発生した場合にメッセージが出力されますので、JNIのパラメーターなどの確認に活用してください。
図1 JNI処理異常時にメッセージを出力するオプション
-Xcheck:jni |
上記の“-Xcheck:jni”パラメーターを指定したときに、図2のメッセージが出力されることがあります。
図2 JNI処理異常時に出力されるメッセージ
FATAL ERROR in native method: (詳細メッセージ) |
“(詳細メッセージ)”の部分には、以降で説明する文字列が出力されます。
以降、図2の“詳細メッセージ”が出力される例と注意事項を説明します。
以降の説明を参考にして、JNIの処理部分を見直してください。
メッセージの説明
[異常例]
char buf[1]; |
[異常例]
(*env)->AllocObject(env, NULL); //jclass型の第2引数にnullを指定 |
[異常例]
(*env)->GetStringUTFChars(env, NULL, 0); //jstring型の第2引数にNULLを指定 |
[異常例]
(*env)->GetArrayLength(env, (jarray)(*env)->NewStringUTF(env, "abc")); //jarray型の第2引数に配列でない型を指定 |
[注意事項]
次の場合は、“-Xcheck:jni”オプションによるメッセージは出力されません。
char buf[1]; |
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[注意事項]
instance変数かどうかのチェック時のみに出力されるメッセージです。
次の場合は、“-Xcheck:jni”オプションによるメッセージは出力されません。
(*env)->GetObjectClass(env, NULL); //objectの第2引数にNULLを指定 |
[異常例]
(*env)->GetIntField(env, obj, -1); //jfieldID型の第3引数に数値を指定 |
[注意事項]
instance変数かどうかのチェック時のみに出力されるメッセージです。
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[注意事項]
次の場合は、“-Xcheck:jni”オプションによるメッセージは出力されません。
jclass cls = (*env)->GetObjectClass(env, obj); |
[異常例]
jintArray intarray = (*env)->NewIntArray(env, 2); |
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[異常例]
jclass cls = (*env)->GetObjectClass(env, obj); |
[解説]
実行しているスレッドのためのものではないJNIEnvを使用したためのエラーです。
Java VMは、JNIインタフェースポインタ(JNIEnv)が参照する領域を、スレッド固有のデータ領域に割り当てることがあります。このため、JNIインタフェースポインタは、カレントスレッドに対してのみ有効です。ネイティブメソッドは、JNIインタフェースポインタを別のスレッドに渡すといった使い方はできません。
[解説]
ネイティブプログラムで何らかの例外が発生後、その例外を処理せずに引き続きJNI関数を実行したためのエラーです。
ネイティブプログラムでJNI関数を呼び出した後は、その都度ExceptionOccurredを使用して例外の発生状況をチェックし、必要に応じて、例外のクリア、または、例外を上位メソッドへスローしてください。