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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java如何做全局缓存_传智播客JNI第七讲 – JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式...

發(fā)布時(shí)間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java如何做全局缓存_传智播客JNI第七讲 – JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

講解JNI中的全局引用/局部引用/弱全局引用、緩存jfieldID和jmethodID的兩種方式,并編寫兩種緩存方式的示例代碼。

1.從Java虛擬機(jī)創(chuàng)建的對象傳到本地C/C++代碼時(shí)會(huì)產(chǎn)生引用,根據(jù)Java的垃圾回收機(jī)制,只要有引用存在就不會(huì)出發(fā)該引用指向的Java對象的垃圾回收。

2.這些引用在JNI中分為三種:

全局引用:Global Reference

局部引用:Local Reference

若全局引用:Weak Global Reference since JDK1.2

3.局部引用

1)最常見的引用類型,基本上通過JNI返回來的引用都是局部引用。例如使用NewObject就會(huì)返回創(chuàng)建出來的實(shí)例的局部引用,局部引用只在該native函數(shù)中有效,所有在該函數(shù)中產(chǎn)生的局部引用,都會(huì)在函數(shù)返回的時(shí)候自動(dòng)釋放,也可以使用DeleteLocalRef函數(shù)手動(dòng)釋放該引用。

2)想一想既然局部引用能夠在函數(shù)返回時(shí)自動(dòng)釋放,為什么還需要DeleteLocalRef函數(shù)呢?

3)實(shí)際上,局部引用存在,就會(huì)防止其指向的對象被垃圾回收,尤其是當(dāng)一個(gè)局部引用指向一個(gè)很龐大的對象,或是在一個(gè)循環(huán)中生成了局部引用,最好的做法就是在使用完該對象后,或在循環(huán)尾部把這個(gè)引用釋放掉,以確保在垃圾回收器被處罰的時(shí)候被回收。

4)在局部引用的有效期中,可以傳遞到別的本地函數(shù)中,要強(qiáng)調(diào)的是他的有效期仍然只在一次的Java本地函數(shù)調(diào)用中,所以千萬不能用C++全局變量保存它或者把它定義為C++靜態(tài)局部變量。

4.全局引用

1)全局引用可以跨越當(dāng)前線程,在多個(gè)native函數(shù)中有效,不過需要編程人員手動(dòng)來釋放該引用,全局引用存在期間會(huì)防止在Java的垃圾回收。

2)與局部引用不同,全局引用的創(chuàng)建不是由JNI自動(dòng)創(chuàng)建的,全局引用時(shí)需要調(diào)用NewGlobalRef函數(shù),而釋放它需要使用ReleaseGlobalRef函數(shù)。

5.弱全局引用

1)Java1.2新出來的功能,與全局引用相似,創(chuàng)建跟刪除都需要由編程人員來進(jìn)行。這種引用與全局引用一樣可以再多個(gè)本地代碼有效,也跨越多線程有效,不一樣的是,這種引用將不會(huì)阻止垃圾回收器回收這個(gè)引用所指向的對象。

2)使用NewWeakGlobalRef跟ReleaseWeakGlobalRef來產(chǎn)生和解除引用。

6.關(guān)于引用的一些函數(shù)

jobject NewGlobalRef(jobject obj);

jobject NewLocalRef(jobject obj);

jobject NewWeakGlobalRef(jobject obj);

void DeleteGlobalRef(jobject obj);

void DeleteLocalRef(jobject obj);

void DeleteWeakGlobalRef(jobject obj);

jboolean IsSameObject(jobject obj1, jobject obj2); // 這個(gè)函數(shù)對于弱全局引用還有一個(gè)特別的功能,把NULL傳入要比較的對象中,就能夠判斷弱全局引用所指向的Java對象是否被回收。

7.緩存jfieldID,jmethodID

1)取得jieldID跟jmethodID的時(shí)候會(huì)通過該屬性、方法名稱加上簽名來查詢相應(yīng)的jfieldID,jmethodID。這種查詢相對來說開銷較大,我們可以將這些FieldID,MethodID緩存起來,這樣只需要查詢一次,以后就使用緩存起來的FieldID,MethodID。

2)介紹兩種緩存方式

1.在用的時(shí)候緩存

2.在Java類初始化時(shí)緩存

11)在第一次使用的時(shí)候緩存

在native code中使用static局部變量來保存已經(jīng)查詢過的id,這樣就不會(huì)再每次的函數(shù)調(diào)用時(shí)查詢,而只要第一次查詢成功后就保存起來了。

不過在這種情況下就不得不考慮多線程同時(shí)呼叫此函數(shù)時(shí)可能會(huì)招致同時(shí)查詢的危機(jī),不過這種情況是無害的,因?yàn)椴樵兺粋€(gè)屬性,方法的ID通常返回的是一樣的值。

JNIEXPORT void JNICALL Java_Test_native(JNIEnv* env, jobject obj){

static jfieldID fieldID_string = NULL;

jclass clazz = env->GEtObjectClass(obj);

if(fieldID_string == NULL){

fieldID_string = env->GetFieldID(clazz, "string", "Ljava/lang/String;");

}

// other code...

}

22)在Java類初始化的時(shí)候緩存

更好的一個(gè)方式就是在任何native函數(shù)調(diào)用前把id全部存起來。

我們可以讓Java在第一次加載這個(gè)類的時(shí)候首先調(diào)用本地代碼初始化所有的jfieldID,jmethodID,這樣的話,就可以省去多次的確定id是否存在的語句,當(dāng)然,這些jfieldID,jmethodID是定義在C/C++的全局。

使用這種方式的好處,當(dāng)Java類卸載或是重新加載的時(shí)候,也會(huì)重新呼叫該本地代碼來重新計(jì)算IDs。

課程最后總結(jié)

在這一課中,我們學(xué)習(xí)了:

1.最簡單的Java調(diào)用C/C++函數(shù)的方法

2.取得方法、屬性的ID,學(xué)會(huì)了取得/設(shè)置屬性,還有Java函數(shù)的調(diào)用。

3.Java/c++之間的字符串的轉(zhuǎn)換問題。

4.在C/C++下如何操作Java數(shù)組。

5.三種引用方式

6.如何緩存屬性和方法的ID

使用JNI的兩個(gè)弊端

1.使用了JNI,那么這個(gè)應(yīng)用就不能跨平臺(tái)了,如果需要移植到別的平臺(tái)上,那么native代碼就需要重新編寫。

2.Java是強(qiáng)類型的語言,而C/C++不是,你必須寫JNI時(shí)更小心。

3.盡量少使用本地代碼。

其它

1.異常處理

2.C/C++如何啟動(dòng)JVM

3.JNI跟多線程

介紹兩本書作為參考:

1)The Java Native Interface Programmer's Guide and Specification

2))JNI++ User Guide

總結(jié)

以上是生活随笔為你收集整理的java如何做全局缓存_传智播客JNI第七讲 – JNI中的全局引用/局部引用/弱全局引用、缓存jfieldID和jmethodID的两种方式...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。