當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 程序喵大人
[導(dǎo)讀]最近開(kāi)發(fā)過(guò)程中遇到了JNI的Reference相關(guān)問(wèn)題,了解到Local Reference和Global Reference的相關(guān)知識(shí)點(diǎn),整理如下: 背景:項(xiàng)目需求,在Native C/C++層調(diào)用上層Android Camera Java接口,把所有的操作包括Camera都沉到Native層去實(shí)現(xiàn)。但在JNI調(diào)試過(guò)程中遇到了


最近開(kāi)發(fā)過(guò)程中遇到了JNI的Reference相關(guān)問(wèn)題,了解到Local Reference和Global Reference的相關(guān)知識(shí)點(diǎn),整理如下:

背景:項(xiàng)目需求,在Native C/C++層調(diào)用上層Android Camera Java接口,把所有的操作包括Camera都沉到Native層去實(shí)現(xiàn)。但在JNI調(diào)試過(guò)程中遇到了android JNI ERROR (app bug): accessed stale local reference的報(bào)錯(cuò)。

現(xiàn)象:在Native層創(chuàng)建Java的Camera對(duì)象,其對(duì)象的指針保存到本地,函數(shù)返回到Java層,之后再進(jìn)入Native層,想通過(guò)Native層的Camera對(duì)象指針調(diào)用相應(yīng)的方法,但是發(fā)現(xiàn)每次都是重新調(diào)用Java對(duì)象方法后報(bào)錯(cuò)。

分析:在Native層創(chuàng)建的Java對(duì)象,對(duì)象創(chuàng)建后會(huì)有一個(gè)局部引用指向該對(duì)象,當(dāng)從Native環(huán)境返回到Java環(huán)境,該局部引用失效,此對(duì)象就沒(méi)有引用計(jì)數(shù),Java的內(nèi)存回收機(jī)制會(huì)自動(dòng)回收該對(duì)象,第二次再進(jìn)入Native層訪問(wèn)其之前保存的地址時(shí)就會(huì)報(bào)錯(cuò)。

解決:使用全局引用始終持有該對(duì)象的引用使其不被自動(dòng)回收,請(qǐng)看下面的知識(shí)點(diǎn)。

Local Reference

局部引用,看如下精簡(jiǎn)代碼:

env->NewStringUTF("0");

在JNI中,每次調(diào)用NewObject方法創(chuàng)建一個(gè)新的對(duì)象都會(huì)返回一個(gè)對(duì)該對(duì)象的局部引用(Local Reference),該局部引用只在線程當(dāng)前的Native環(huán)境中有效,返回到Java環(huán)境后該引用與對(duì)象之間的聯(lián)系就會(huì)被斷掉,引用失效,所以我們不能在Native方法中把局部引用緩存用于下一次調(diào)用時(shí)使用。

局部引用可以無(wú)限創(chuàng)建嗎?

如圖:


這里引入局部引用表的概念,每當(dāng)線程從Java環(huán)境進(jìn)入到Native環(huán)境后,JVM就會(huì)創(chuàng)建該線程N(yùn)ative環(huán)境的局部引用表,用來(lái)保存本次Native環(huán)境所創(chuàng)建的所有局部引用,每當(dāng)Native中引用或者新創(chuàng)建一個(gè)Java對(duì)象,JVM就會(huì)局部引用表創(chuàng)建一個(gè)局部引用,局部引用表是有大小限制的,最大是512,如果超過(guò)限制會(huì)報(bào)OOM內(nèi)存泄漏。

Q:那如何才能更好的避免由于局部引用過(guò)多造成Native環(huán)境中的OOM呢?

A:控制局部引用的生命周期,如果需要?jiǎng)?chuàng)建過(guò)多的局部引用,可以在Java對(duì)象的操作結(jié)束后,手動(dòng)調(diào)用DeleteLocalRef函數(shù)刪除局部引用,該局部引用就會(huì)在局部引用表中被移除,避免觸發(fā)局部引用表的大小限制。

注意:局部引用不是我們平時(shí)所理解的代碼中的局部變量,局部變量在當(dāng)前生命周期(例如函數(shù)退出)結(jié)束后就會(huì)失效,而局部引用在函數(shù)退出后可能不會(huì)失效,它的生命周期是和整個(gè)Native上下文環(huán)境相關(guān)聯(lián),只有從Native環(huán)境返回到Java環(huán)境后局部引用才會(huì)失效。

Global Reference

全局引用,終于到了最上面討論的問(wèn)題了,因?yàn)榫植恳迷贜ative環(huán)境返回到Java環(huán)境后就會(huì)失效,導(dǎo)致下次進(jìn)入Native環(huán)境后再次使用相對(duì)應(yīng)的Java對(duì)象就會(huì)出錯(cuò),所以可以使用全局引用來(lái)解決這個(gè)問(wèn)題,全局引用可以始終與Java對(duì)象保持聯(lián)系,使得此對(duì)象不會(huì)被JVM回收掉,見(jiàn)如下代碼:

JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved) {  jclass tmp = env->FindClass("com/example/company/MyClass");  jclass class = env->NewGlobalRef(tmp); return JNI_VERSION_1_6; }

這里需要注意,在不需要使用Java對(duì)象后盡量手動(dòng)調(diào)用DeleteGlobalRef()函數(shù)來(lái)使得引用失效,避免對(duì)象始終存在,產(chǎn)生潛在的內(nèi)存泄漏。

Weak Global Reference

虛全局引用與全局引用的區(qū)別在于該類型的引用可能隨時(shí)被JVM回收掉,這里涉及到幾個(gè)函數(shù):

NewWeakGlobalRef();DeleteWeakGlobalRef();isSameObject();

在使用虛引用前需要通過(guò)isSameObject將其和NULL比較,如果返回true表示已經(jīng)被JVM回收掉就不能使用了,這里有可能前一行代碼判斷還是可用,后一行代碼時(shí)就被JVM回收,解決辦法是通過(guò)NewLocalRef()獲取虛全局引用,避免當(dāng)時(shí)被JVM回收。

參考資料

https://www.cnblogs.com/zhongshujunqia/p/4638077.html?utm_source=tuicool&utm_medium=referral
https://www.cnblogs.com/younghome/p/4609044.html
https://stackoverflow.com/questions/14765776/jni-error-app-bug-accessed-stale-local-reference-0xbc00021-index-8-in-a-tabl
https://www.ibm.com/developerworks/cn/java/j-lo-jnileak/index.html
https://juejin.im/post/5c19bfa0f265da6133568545



c++11新特性,所有知識(shí)點(diǎn)都在這了!

你的c++團(tuán)隊(duì)還在禁用異常處理嗎?

內(nèi)存對(duì)齊之格式修訂版

c++11新特性之智能指針

gcc a.c 究竟經(jīng)歷了什么?

談?wù)劤绦蜴溄蛹胺侄文切┦?/span>

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉