Interstage Application Server トラブルシューティング集 |
目次
索引
![]() ![]() |
第19章 Java実行環境運用時の異常 |
Java以外の言語と連携する場合、Java Native Interface(以降、JNIと略記)を使用します。
しかし、JNIの使用方法を誤ると、異常終了などの原因となります。
この場合、以下の方法で実行時のJNIのパラメータの確認を行うことができます。
製品添付のJDK/JRE1.3、1.4のいずれでも有効です。
Java VM起動時に“-Xcheck:jni”オプションを指定したとき、JNI処理で異常がある場合に出力されるメッセージと、その例を以下に説明します。以下を参考にして、JNIの処理部を修正してください。
XXXXの部分には、以下が出力されます。
char buf[1]; (*env)->AllocObject(env, (jclass)buf); //jclass型の第2引数に違う型を指定
(*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]; (*env)->GetArrayLength(env, (jarray)buf);
jclass cls = (*env)->GetObjectClass(env, obj); jfieldID fid = (*env)->GetFieldID(env, cls, "static_data", "I"); (*env)->GetIntField(env, obj, fid); //jfieldID型の第3引数にstaticフィールドを指定
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を指定
(*env)->GetIntField(env, obj, -1); //jfieldID型の第3引数に数値を指定
このエラーは、instance変数かどうかのチェック時のみに出力されるエラーです。
jclass cls = (*env)->GetObjectClass(env, obj); (*env)->GetStaticIntField(env, cls, -1); //jfiedlID型第2引数に数値を指定
以下の場合では、-Xcheck:jniはエラーを検出せず、通常のエラーとなります。
jclass cls = (*env)->GetObjectClass(env, obj); jfieldID fid = (*env)->GetStaticFieldID(env, cls, "instance_data", "I"); (*env)->GetStaticIntField(env, cls, fid);
jintArray intarray = (*env)->NewIntArray(env, 2); (*env)->GetFloatArrayElements(env, intarray, 0); //floatArray型の第2引数にjintArrayを指定
jclass cls = (*env)->GetObjectClass(env, obj); jobjectArray objarray = (*env)->NewObjectArray(env, 1, cls, obj); (*env)->GetIntArrayElements(env, objarray, 0); //intArray型の第2引数にjobjectArray型を指定
jclass cls = (*env)->GetObjectClass(env, obj); jfieldID fid = (*env)->GetStaticFieldID(env, cls, "static_data", "I"); (*env)->GetStaticFloatField(env, cls, fid); //GetStaticFloatFieldではなくGetStaticIntFieldでなければならない
jclass cls = (*env)->GetObjectClass(env, obj); jfieldID fid = (*env)->GetFieldID(env, cls, "instance_data", "I"); (*env)->GetFloatField(env, obj, fid); //GetFloatFieldではなくGetIntFieldでなければならない
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でなければならない
実行しているスレッドのためのものではないJNIEnvを使用したためのエラーです。
Java VMは、JNIインタフェースポインタ(JNIEnv)が参照する領域を、スレッド固有のデータ領域に割り当てることがあります。
このため、JNIインタフェースポインタは、カレントスレッドに対してのみ有効です。ネイティブメソッドは、JNIインタフェースポインタを別のスレッドに渡すといった使い方はできません。
また、JNIの使用方法に誤りがなくてもJNI使用時に異常終了やハングが発生することがあります。原因としてnative側でハングや異常終了するケースが考えられます。特にnative側でスレッドアンセーフな関数を使用した場合に注意が必要です。
特に、以下の関数を使用したときに、ハングした事例があります。
目次
索引
![]() ![]() |