Interstage Application Server トラブルシューティング集
目次 索引 前ページ次ページ

第19章 Java実行環境運用時の異常

19.6 JNI使用時の注意事項

 Java以外の言語と連携する場合、Java Native Interface(以降、JNIと略記)を使用します。
しかし、JNIの使用方法を誤ると、異常終了などの原因となります。

 この場合、以下の方法で実行時のJNIのパラメータの確認を行うことができます。

■動作環境

 製品添付のJDK/JRE1.3、1.4のいずれでも有効です。

■出力情報と解析

 Java VM起動時に“-Xcheck:jni”オプションを指定したとき、JNI処理で異常がある場合に出力されるメッセージと、その例を以下に説明します。以下を参考にして、JNIの処理部を修正してください。

◆“FATAL ERROR in native method: XXXX”

 XXXXの部分には、以下が出力されます。

  1. “JNI received a class argument that is not a class”

    char buf[1];
    (*env)->AllocObject(env, (jclass)buf); //jclass型の第2引数に違う型を指定
    
  2. “JNI received a null class”

    (*env)->AllocObject(env, NULL); //jclass型の第2引数にnullを指定
    
  3. “JNI string operation received a non-string”

    (*env)->GetStringUTFChars(env, NULL, 0); //jstring型の第2引数にNULLを指定
  4. “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);
    
  5. “Static field ID passed to JNI”

    jclass cls = (*env)->GetObjectClass(env, obj);
    jfieldID fid = (*env)->GetFieldID(env, cls, "static_data", "I"); (*env)->GetIntField(env, obj, fid); //jfieldID型の第3引数にstaticフィールドを指定
  6. “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を指定
  7. “Wrong field ID passed to JNI”

    (*env)->GetIntField(env, obj, -1); //jfieldID型の第3引数に数値を指定

    このエラーは、instance変数かどうかのチェック時のみに出力されるエラーです。

  8. “Non-static field ID passed to JNI”

    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);
  9. “Array element type mismatch in JNI”

    jintArray intarray = (*env)->NewIntArray(env, 2);
    (*env)->GetFloatArrayElements(env, intarray, 0); //floatArray型の第2引数にjintArrayを指定
  10. “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型を指定
  11. “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でなければならない
  12. “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でなければならない
  13. “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でなければならない
  14. “Using JNIEnv in the wrong thread"

     実行しているスレッドのためのものではないJNIEnvを使用したためのエラーです。
     Java VMは、JNIインタフェースポインタ(JNIEnv)が参照する領域を、スレッド固有のデータ領域に割り当てることがあります。
     このため、JNIインタフェースポインタは、カレントスレッドに対してのみ有効です。ネイティブメソッドは、JNIインタフェースポインタを別のスレッドに渡すといった使い方はできません。

  15. “Bad global or local ref passed to JNI"

■異常終了の事例

 また、JNIの使用方法に誤りがなくてもJNI使用時に異常終了やハングが発生することがあります。原因としてnative側でハングや異常終了するケースが考えられます。特にnative側でスレッドアンセーフな関数を使用した場合に注意が必要です。

 特に、以下の関数を使用したときに、ハングした事例があります。


目次 索引 前ページ次ページ

Copyright 2006 FUJITSU LIMITED