RegisterNatives
,UnregisterNatives
,ネイティブメソッドのダイナミックリンク処理には 2通りの実行契機(明示的なリンク, 暗黙的なリンク)がある (See: here for details). RegisterNatives() は明示的にリンクする場合の処理を行う.
内部的な処理としては, RegisterNatives() は指定されたアドレス(関数ポインタ)を methodOop 内にセットするだけ (なお, 該当の methodOop を探す際に JVMTI の prefix についての処理が必要なので, find_prefixed_native() による処理も行っている).
逆に UnregisterNatives() では, セットしたアドレスを別のアドレスで上書きして飛べなくするだけ (SharedRuntime::native_method_throw_unsatisfied_link_error_entry() のアドレスで上書きされる).
jni_RegisterNatives() は, ユーザーから明示的に呼び出された場合以外に, HotSpot の内部的な処理からも呼び出されている.
例えば, 標準ライブラリの基本的なクラスのネイティブメソッドは, 以下に示す関数内で RegisterNatives() を使って明示的に CVMI (JVM_*) 関数にバインドされている.
また, NativeLookup で暗黙的にリンクされる場合(See: here for details)でも, 以下に示す一部のメソッドでは jni_RegisterNatives() を呼び出す初期化用関数にハードコーディングされている. そしてそれらの関数の中から jni_RegisterNatives() が呼び出される.
(これらのメソッドでは,
通常のように Java_${mangled fully-qualified class name}_${mangled method name}
という関数が定義されてその中で jni_RegisterNatives() が呼ばれるのではなく,
Java_${mangled fully-qualified class name}_${mangled method name}
が
NativeLookup によって直接 JVM_Register*() という CVMI 関数にバインドされ,
その中で jni_RegisterNatives() がよばれる) (何故こんな風に2種類のやり方が取られている?? #TODO)
jni_RegisterNatives() -> register_native() -> find_prefixed_native() -> methodOopDesc::set_native_function() (or methodOopDesc::clear_native_function())
jni_UnregisterNatives() -> methodOopDesc::clear_native_function() -> methodOopDesc::set_native_function() (飛び先を SharedRuntime::native_method_throw_unsatisfied_link_error_entry() に設定) -> methodOopDesc::clear_code()
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.