日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

java qt jni_java JNI 实现原理 (二) Linux 下如何 load JNILibrary

發布時間:2025/7/14 linux 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java qt jni_java JNI 实现原理 (二) Linux 下如何 load JNILibrary 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在博客java JNI (一)

虛擬機中classloader的JNILibrary 中討論了java中的Library 是由classloader 來load的,那我們來看看 classloader是如何去load 一個library的。

ClassLoader.c

[cpp]

JNIEXPORT voidJNICALL

Java_java_lang_ClassLoader_00024NativeLibrary_load

(JNIEnv*env, jobject this, jstring name)

{const char *cname;

jint jniVersion;

jthrowable cause;void *handle;if (!initIDs(env))return;

cname= JNU_GetStringPlatformChars(env, name, 0);if (cname == 0)return;

handle=JVM_LoadLibrary(cname);if(handle) {const char *onLoadSymbols[] =JNI_ONLOAD_SYMBOLS;

JNI_OnLoad_t JNI_OnLoad;inti;for (i = 0; i < sizeof(onLoadSymbols) / sizeof(char *); i++) {

JNI_OnLoad=(JNI_OnLoad_t)

JVM_FindLibraryEntry(handle, onLoadSymbols[i]);if(JNI_OnLoad) {break;

}

}if(JNI_OnLoad) {

JavaVM*jvm;

(*env)->GetJavaVM(env, &jvm);

jniVersion= (*JNI_OnLoad)(jvm, NULL);

}else{

jniVersion= 0x00010001;

}

cause= (*env)->ExceptionOccurred(env);if(cause) {

(*env)->ExceptionClear(env);

(*env)->Throw(env, cause);

JVM_UnloadLibrary(handle);gotodone;

}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);gotodone;

}

(*env)->SetIntField(env, this, jniVersionID, jniVersion);

}else{

cause= (*env)->ExceptionOccurred(env);if(cause) {

(*env)->ExceptionClear(env);

(*env)->SetLongField(env, this, handleID, (jlong)NULL);

(*env)->Throw(env, cause);

}gotodone;

}

(*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));

done:

JNU_ReleaseStringPlatformChars(env, name, cname);

}

1. JVM_LoadLibrary

jvm中load library 核心函數,實現也非常簡單,在linux下調用了系統函數dlopen去打開庫文件,詳細可參考方法

[cpp]

void * os::dll_load(const char *filename, char *ebuf, int ebuflen)

2. JVM_FindLibraryEntry

JVM在加載庫文件時候,會去嘗試查找庫中的JNI_ONLOAD方法的地址,而在Linux中調用了dlsym函數通過前面的dlopen加載庫的指針去獲取方法的地址,而dlsym在glibc2.0是非線程安全的,需要鎖的保護,雖然在java中加載庫已經有鎖的保護,但只是針對同一個classloader對象的細粒度鎖。

[cpp]

void* os::dll_lookup(void* handle, const char*name) {

pthread_mutex_lock(&dl_mutex);void* res =dlsym(handle, name);

pthread_mutex_unlock(&dl_mutex);returnres;

}

3. 方法JNI_OnLoad

JVM提供了一種方式允許你在加載庫文件的時候做一些你想做的事情,也就是JNI_OnLoad方法

在2中提到過在加載動態鏈接庫,JVM會去嘗試查找JNI_OnLoad方法,同時也會調用該函數,這樣你個人可以在函數里做一些初始化的事情,比如register native方法。

[cpp]

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*reserved)

{}

JNI_OnLoad中返回的是JNI 的version,在1.6版本的情況下支持如下

[cpp]

jboolean Threads::is_supported_jni_version(jint version) {if (version == JNI_VERSION_1_2) returnJNI_TRUE;if (version == JNI_VERSION_1_4) returnJNI_TRUE;if (version == JNI_VERSION_1_6) returnJNI_TRUE;returnJNI_FALSE;

}

完整的加載過程就是

首先先加載動態鏈接庫,嘗試查找JNI_OnLoad方法,并且運行方法,對我們來說從而實現可以自定義的初始化方法。

總結

以上是生活随笔為你收集整理的java qt jni_java JNI 实现原理 (二) Linux 下如何 load JNILibrary的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。