registerNatives()メソッドは何をしますか?
-
06-07-2019 - |
質問
Javaでは、Objectクラスのプライベート静的メソッドregisterNatives()
は何をしますか?
解決
他の答えは技術的には正しいですが、JNIの経験がない人にはあまり役に立ちません。 :-)
通常、JVMがネイティブ関数を見つけるには、特定の方法で名前を付ける必要があります。たとえば、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
がリストにないことに注意してください; <!> quot; standard <!> quot; Java_java_lang_Object_getClass
の名前によって呼び出されます。)リストされた関数の場合、関連するC関数はそのテーブルにリストされているように、多くの転送機能を書くよりも便利です。
ネイティブ関数の登録は、CプログラムにJavaを埋め込み、アプリケーション自体(共有ライブラリ内ではなく)内の関数にリンクしたい場合、または使用されている関数がそうでない場合に便利です<!> quot; exported <!> quot;。これらは通常、標準のメソッド検索メカニズムでは検出されないためです。ネイティブ関数の登録は、<!> quot; rebind <!> quot;にも使用できます。別のC関数へのネイティブメソッド(プログラムがモジュールの動的なロードとアンロードをサポートしている場合などに便利です。
JNI本を読むことをお勧めします。 で、このことなどについて説明しています。 :-)
他のヒント
少し紛らわしいかもしれないのは、前の回答のjava.lang.Object.registerNatives
に示されているコードが、ネイティブ関数を登録する方法の単なる例であるということです。これは、(OpenJDKの実装で)クラスObjectのネイティブ関数を登録するコードです。独自のクラスのネイティブ関数を登録するには、独自のライブラリのネイティブコードからJNI関数RegisterNatives
を呼び出す必要があります。これは少し循環的に聞こえるかもしれませんが、ループを破る方法がいくつかあります。
-
Objectクラスのこの実装の例に従ってください:
a。 Javaクラスで、
registerNatives
(またはその他の名前。重要ではありません)という名前のネイティブメソッド(できれば静的)を宣言します。b。ネイティブコードで、JNI関数
Java_<your fully qualified class name>_registerNatives
への呼び出しを含むJNI_OnLoad
という名前の関数を定義します。c。 Javaコードでは、Java
jint JNI_OnLoad(JavaVM *vm, void *reserved)
メソッドが他のネイティブメソッドの呼び出しの前に呼び出されることを確認してください。
または
-
System.loadLibrary
a。ネイティブライブラリで関数
env
を定義します。この関数の本体で、JNI関数GetEnv
を呼び出します。b。 Java VMは、ネイティブライブラリが
vm
によってロードされたときに自動的に<=>を探して呼び出します。これは、おそらくクラスの静的初期化子で、既に呼び出しているはずです。 (必要な<=>ポインターを取得するには、<=>ポインターが指すテーブルで<=>関数を呼び出します。)