jdk/src/share/native/java/lang/ClassLoader.c
/*
* Class: java_lang_ClassLoader_NativeLibrary
* Method: load
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT void JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_load
(JNIEnv *env, jobject this, jstring name)
{
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
const char *cname;
jint jniVersion;
jthrowable cause;
void * handle;
{- -------------------------------------------
(1) (まだ初期化が終わっていなければ) 初期化を行っておく.
初期化中にエラーが起きた場合は, ここでリターン.
---------------------------------------- -}
if (!initIDs(env))
return;
{- -------------------------------------------
(1) JNU_GetStringPlatformChars() で
ライブラリ名を実行環境の文字エンコーディングに合わせた文字列に変換しておく.
変換処理が失敗したら, ここでリターン.
---------------------------------------- -}
cname = JNU_GetStringPlatformChars(env, name, 0);
if (cname == 0)
return;
{- -------------------------------------------
(1) JVM_LoadLibrary() でライブラリをロードする.
---------------------------------------- -}
handle = JVM_LoadLibrary(cname);
{- -------------------------------------------
(1) (以下の処理は, JVM_LoadLibrary() によるロードの成否に応じて 2通りに分岐)
---------------------------------------- -}
{- -------------------------------------------
(1) もし JVM_LoadLibrary() でのロードが成功していれば, 以下の処理を行う.
---------------------------------------- -}
if (handle) {
{- -------------------------------------------
(1.1) JVM_FindLibraryEntry() を呼んで, JNI_OnLoad シンボルが含まれているかどうかを調べる.
(JNI_OnLoad を示すシンボルはプラットフォームによっては候補が複数あることがあるため, ループで処理.
候補のどれかが見つかれば終了.)
---------------------------------------- -}
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
JNI_OnLoad_t JNI_OnLoad;
unsigned int i;
for (i = 0; i < sizeof(onLoadSymbols) / sizeof(char *); i++) {
JNI_OnLoad = (JNI_OnLoad_t)
JVM_FindLibraryEntry(handle, onLoadSymbols[i]);
if (JNI_OnLoad) {
break;
}
}
{- -------------------------------------------
(1.1) もし JNI_OnLoad シンボルが見つかれば, それを呼び出し, 返値から jni version を取得する.
JNI_OnLoad シンボルが見つからなかった場合は, jni version は 1.1 とする.
---------------------------------------- -}
if (JNI_OnLoad) {
JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm);
jniVersion = (*JNI_OnLoad)(jvm, NULL);
} else {
jniVersion = 0x00010001;
}
{- -------------------------------------------
(1.1) もし例外が発生していたら, JVM_UnloadLibrary() でライブラリをアンロードする.
(発生した例外はそのまま rethrow)
---------------------------------------- -}
cause = (*env)->ExceptionOccurred(env);
if (cause) {
(*env)->ExceptionClear(env);
(*env)->Throw(env, cause);
JVM_UnloadLibrary(handle);
goto done;
}
{- -------------------------------------------
(1.1) もしロードしたライブラリの jni version がサポート対象外であれば,
UnsatisfiedLinkError を送出し, ロードしたライブラリも JVM_UnloadLibrary() でアンロードする.
---------------------------------------- -}
if (!JVM_IsSupportedJNIVersion(jniVersion)) {
char msg[256];
jio_snprintf(msg, sizeof(msg),
"unsupported JNI version 0x%08X required by %s",
jniVersion, cname);
JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
JVM_UnloadLibrary(handle);
goto done;
}
{- -------------------------------------------
(1.1) 取得した jniVersion 情報を, NativeLibrary の jniVersion フィールドにセットする.
---------------------------------------- -}
(*env)->SetIntField(env, this, jniVersionID, jniVersion);
{- -------------------------------------------
(1) もし JVM_LoadLibrary() でのロードが失敗していれば,
NativeLibrary の handle フィールドを 0 にセットした後, 同じ例外を rethrow する.
---------------------------------------- -}
} else {
cause = (*env)->ExceptionOccurred(env);
if (cause) {
(*env)->ExceptionClear(env);
(*env)->SetLongField(env, this, handleID, (jlong)0);
(*env)->Throw(env, cause);
}
goto done;
}
{- -------------------------------------------
(1) NativeLibrary の handle フィールドにロード結果のポインタを格納する.
---------------------------------------- -}
(*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));
{- -------------------------------------------
(1) (後始末)
---------------------------------------- -}
done:
JNU_ReleaseStringPlatformChars(env, name, cname);
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.