78

Javaでは、Objectクラスのprivate staticメソッドregisterNatives()は何をしますか?

4

3 に答える 3

121

他の回答は技術的には正しいですが、JNI の経験がない人にとってはあまり役に立ちません。:-)

通常、JVM がネイティブ関数を見つけるには、特定の方法で名前を付ける必要があります。たとえば、 for のjava.lang.Object.registerNatives場合、対応する C 関数の名前はJava_java_lang_Object_registerNativesです。registerNatives(というか、JNI 関数) を使用RegisterNativesすることで、C 関数に好きな名前を付けることができます。

関連する C コードは次のとおりです (OpenJDK 6 から)。

static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

( はリストにないことに注意しObject.getClassてください。これは引き続き の「標準」名で呼び出されJava_java_lang_Object_getClassます。) リストされた関数については、関連する C 関数がその表にリストされているとおりであり、転送関数の束を記述するよりも便利です。

ネイティブ関数の登録は、Java を C プログラムに組み込み、(共有ライブラリ内ではなく) アプリケーション自体内の関数にリンクしたい場合、または使用されている関数が「エクスポート」されない場合にも役立ちます。通常、標準のメソッド ルックアップ メカニズムでは検出されません。ネイティブ関数の登録は、ネイティブ メソッドを別の C 関数に「再バインド」するためにも使用できます (たとえば、プログラムがモジュールの動的なロードとアンロードをサポートしている場合に役立ちます)。

JNIの書籍 を読むことをお勧めします。この本では、このことやその他多くのことが説明されています。:-)

于 2009-06-18T12:40:19.183 に答える
11

少し混乱するかもしれませんがjava.lang.Object.registerNatives、前の回答で示したコードは、ネイティブ関数を登録する方法の単なる例です。これは、(OpenJDK の実装で) クラス Object のネイティブ関数を登録するコードです。RegisterNatives独自のクラスにネイティブ関数を登録するには、独自のライブラリのネイティブ コードからJNI 関数を呼び出す必要があります。これは少し循環しているように聞こえるかもしれませんが、ループを断ち切る方法がいくつかあります。

  1. クラス Object のこの実装の例に従います。

    を。Java クラスで、ネイティブ メソッド (可能であれば静的) を宣言しますregisterNatives(または他の名前。問題ありません)。

    b. ネイティブ コードでJava_<your fully qualified class name>_registerNatives、JNI 関数 への呼び出しを含むという名前の関数を定義しますRegisterNatives

    c. registerNativesJava コードでは、Javaメソッドが他のネイティブ メソッドの呼び出しの前に呼び出されることを確認してください。

また

  1. 使用するJNI_OnLoad

    を。ネイティブ ライブラリで関数を定義しますjint JNI_OnLoad(JavaVM *vm, void *reserved)。この関数の本体で、JNI 関数を呼び出しますRegisterNatives

    b. JNI_OnLoadネイティブ ライブラリが によってロードされると、 Java VM は自動的に検索して呼び出しますSystem.loadLibrary。これは、おそらくクラスの静的初期化子で既に呼び出しているはずです。(ポインターが指すテーブル内envの関数を呼び出すことによって、必要なポインターを取得します。)GetEnvvm

于 2012-11-07T00:09:28.663 に答える