Android開發(fā)之JNI內(nèi)存模型

  • Java 與JNI 內(nèi)存管理是怎樣的
    想要弄清楚Java與JNI的內(nèi)存管理的關系引颈,首先要弄清楚JVM的內(nèi)存模型
JVM內(nèi)存模型.png

其中本地方法棧就是運行時調(diào)用native 方法的數(shù)據(jù)保存區(qū)沦童。

本地方法棧的大小可以設置成固定的或者是動態(tài)擴展。

  • Java中的內(nèi)存泄露

JAVA 編程中的內(nèi)存泄漏撑教,從泄漏的內(nèi)存位置角度可以分為兩種:JVM 中 Java Heap 的內(nèi)存泄漏朝墩;JVM 內(nèi)存中 native memory 的內(nèi)存泄漏。

  • Java Heap 的內(nèi)存泄漏

    • Java 對象存儲在 JVM 進程空間中的 Java Heap 中伟姐,Java Heap 可以在 JVM 運行過程中動態(tài)變化收苏。如果 Java 對象越來越多亿卤,占據(jù) Java Heap 的空間也越來越大,JVM 會在運行時擴充 Java Heap 的容量鹿霸。如果 Java Heap 容量擴充到上限排吴,并且在 GC 后仍然沒有足夠空間分配新的 Java 對象,便會拋出 out of memory 異常懦鼠,導致 JVM 進程崩潰钻哩。
    • Java Heap 中 out of memory 異常的出現(xiàn)有兩種原因:①程序過于龐大,致使過多 Java 對象的同時存在肛冶;②程序編寫的錯誤導致 Java Heap 內(nèi)存泄漏憋槐。多種原因可能導致 Java Heap 內(nèi)存泄漏。JNI 編程錯誤也可能導致 Java Heap 的內(nèi)存泄漏淑趾。
  • JVM 中 native memory 的內(nèi)存泄漏
    JVM 進程空間中阳仔,Java Heap 以外的內(nèi)存空間稱為 JVM 的 native memory。進程的很多資源都是存儲在 JVM 的 native memory 中扣泊,例如載入的代碼映像近范,線程的堆棧,線程的管理控制塊延蟹,JVM 的靜態(tài)數(shù)據(jù)评矩、全局數(shù)據(jù)等等。也包括 JNI 程序中 native code 分配到的資源阱飘。

    JNI編程中的內(nèi)存泄露

    • Native Code 本身的內(nèi)存泄漏

    • Global Reference 引入的內(nèi)存泄漏

    • JNI 編程中潛在的內(nèi)存泄漏斥杜,特別是LocalReference的使用

  • 哪些情況下需要做內(nèi)存管理?

    • native code本身需要做內(nèi)存管理
    如使用c/c++語言編寫沥匈,需要遵守語言本身的內(nèi)存管理策略蔗喂,如指針變量的創(chuàng)建于釋放不當都可能產(chǎn)生內(nèi)存泄露,進一步導致內(nèi)存JVM的崩潰高帖。
    
    • Global Reference的管理
    而 Global Reference 對 Java 對象的引用一直有效缰儿,因此它們引用的 Java 對象會一直存在 Java Heap 中。在使用 Global Reference 時散址,需要仔細維護對 Global Reference 的使用乖阵。如果一定要使用 Global Reference,務必確保在不用的時候刪除预麸。就像在 C 語言中瞪浸,調(diào)用 malloc() 動態(tài)分配一塊內(nèi)存之后,調(diào)用 free() 釋放一樣吏祸。否則对蒲,Global Reference 引用的 Java 對象將永遠停留在 Java Heap 中,造成 Java Heap 的內(nèi)存泄漏。
    
    • Local Reference的管理
      Local Reference管理模型圖


      localReference_Java_map.jpg

從這個映射關系表可以看出齐蔽,實際上,每當線程從 Java 環(huán)境切換到 native code 上下文時(J2N)床估,JVM 會分配一塊內(nèi)存含滴,創(chuàng)建一個 Local Reference 表,這個表用來存放本次 native method 執(zhí)行中創(chuàng)建的所有的 Local Reference丐巫。每當在 native code 中引用到一個 Java 對象時谈况,JVM 就會在這個表中創(chuàng)建一個 Local Reference:

  • 運行 native method 的線程的堆棧記錄著 Local Reference 表的內(nèi)存位置(指針 p)

  • Local Reference 表中存放 JNI Local Reference,實現(xiàn) Local Reference 到 Java 對象的映射递胧。

  • native method 代碼間接訪問 Java 對象(java obj1碑韵,java obj2)。通過指針 p 定位相應的 Local Reference 的位置缎脾,然后通過相應的 Local Reference 映射到 Java 對象祝闻。

  • 當 native method 引用一個 Java 對象時,會在 Local Reference 表中創(chuàng)建一個新 Local Reference遗菠。在 Local Reference 結構中寫入內(nèi)容联喘,實現(xiàn) Local Reference 到 Java 對象的映射。

  • native method 調(diào)用 DeleteLocalRef() 釋放某個 JNI Local Reference 時辙纬,首先通過指針 p 定位相應的 Local Reference 在 Local Ref 表中的位置豁遭,然后從 Local Ref 表中刪除該 Local Reference,也就取消了對相應 Java 對象的引用(Ref count 減 1)贺拣。

  • 當越來越多的 Local Reference 被創(chuàng)建蓖谢,這些 Local Reference 會在 Local Ref 表中占據(jù)越來越多內(nèi)存。當 Local Reference 太多以至于 Local Ref 表的空間被用光譬涡,JVM 會拋出異常闪幽,從而導致 JVM 的崩潰。

Local Reference 不是native code的局部變量涡匀,區(qū)別體現(xiàn)在:

  1. 局部變量存儲在線程堆棧中沟使,而 Local Reference 存儲在 Local Ref 表中。

  2. 局部變量在函數(shù)退棧后被刪除渊跋,而 Local Reference 在調(diào)用 DeleteLocalRef() 后才會從 Local Ref 表中刪除腊嗡,并且失效,或者在整個 Native Method 執(zhí)行結束后被刪除拾酝。

  3. 可以在代碼中直接訪問局部變量燕少,而 Local Reference 的內(nèi)容無法在代碼中直接訪問,必須通過 JNI function 間接訪問蒿囤。JNI function 實現(xiàn)了對 Local Reference 的間接訪問客们,JNI function 的內(nèi)部實現(xiàn)依賴于具體 JVM。

具體關于JNI內(nèi)存泄露的實例分析可以參考IBM開發(fā)者社區(qū)的一篇文章:在 JNI 編程中避免內(nèi)存泄漏

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市底挫,隨后出現(xiàn)的幾起案子恒傻,更是在濱河造成了極大的恐慌,老刑警劉巖建邓,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盈厘,死亡現(xiàn)場離奇詭異,居然都是意外死亡官边,警方通過查閱死者的電腦和手機沸手,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來注簿,“玉大人契吉,你說我怎么就攤上這事」羁剩” “怎么了捐晶?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長妄辩。 經(jīng)常有香客問我租悄,道長,這世上最難降的妖魔是什么恩袱? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任泣棋,我火速辦了婚禮,結果婚禮上畔塔,老公的妹妹穿的比我還像新娘潭辈。我一直安慰自己,他們只是感情好澈吨,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布把敢。 她就那樣靜靜地躺著,像睡著了一般谅辣。 火紅的嫁衣襯著肌膚如雪修赞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天桑阶,我揣著相機與錄音柏副,去河邊找鬼。 笑死蚣录,一個胖子當著我的面吹牛割择,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播萎河,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼荔泳,長吁一口氣:“原來是場噩夢啊……” “哼蕉饼!你這毒婦竟也來了?” 一聲冷哼從身側響起玛歌,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤昧港,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后支子,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體创肥,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年译荞,在試婚紗的時候發(fā)現(xiàn)自己被綠了唤冈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凡恍。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖践盼,靈堂內(nèi)的尸體忽然破棺而出塔猾,到底是詐尸還是另有隱情篙骡,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布丈甸,位于F島的核電站糯俗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏睦擂。R本人自食惡果不足惜得湘,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望顿仇。 院中可真熱鬧淘正,春花似錦、人聲如沸臼闻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽述呐。三九已至惩淳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乓搬,已是汗流浹背思犁。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留进肯,地道東北人抒倚。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像坷澡,于是被迫代替她去往敵國和親托呕。 傳聞我的和親對象是個殘疾皇子含蓉,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容