android 記憶體回收

來源:互聯網
上載者:User

標籤:

  昨天朋友問我,如果一個java局部對象在調用jni的時候,如果java層沒有引用它,這個對象會不會因為被jni層引用不被GC,導致記憶體流失。我大概想了一下,說不會。當時想的很簡單,c裡面沒有像java一樣的類似的記憶體回收機制,java層進入jni時值傳遞,不會導致引用產生。實事上比想象的複雜的多,而且並不是這樣的。  

  按照這種想法,如果java層的對象被jni引用時不會計數,對象被GC時,jni層會產生野指標。事實並不是這樣。

  首先GC是發生在進程範圍內的堆空間,如果堆裡的對象沒有被引用,是要被GC回收的。jni層也會在堆上建立對象,照樣能被GC。

  java的記憶體回收可以用表示。

  

如果heap裡面的對象沒有被Stack引用到,即紅色的地區,是要被回收的。總的來說,只要對象沒有被GC root直接或間接引用到就會被GC。

jni調用產生時,jvm的記憶體分布是這個樣子的。

它有兩個棧,一個是java棧,另外一個是native 棧。當一個java調用jni時,棧幀布局其實是這個樣子。

這個是棧幀,所示,該線程首先調用了兩個Java方法,而第二個Java方法又調用了一個本地方法,這樣導致虛擬機器使用了一個本地方法棧。圖中的本地方法棧顯示為 一個連續的記憶體空間。假設這是一個C語言棧,期間有兩個C函數,他們都以包圍在虛線中的灰色塊表示。第一個C函數被第二個Java方法當做本地方法調用, 而這個C函數又調用了第二個C函數。之後第二個C函數被第二個Java方法當做本地方法調用,而這個C函數又調用了第二個C函數。之後第二個C函數又通過 本地方法介面回調了一個Java方法(第三個Java方法)。最終這個Java方法又調用了一個Java方法(他成為圖中的當前方法) 。

 

剛才說到只要對象沒有被GC root直接或間接引用到就會被GC。GC root到底是什麼呢?

JVM對那些沒有根引用的對象進行來及回收,也就是無法從根對象中追述的對象。
JVM記憶體回收的根對象的範圍有以下幾種:
1、棧中引用的對象,引用是在棧幀中的本地變數表中的,真正的對象在堆中
2、方法區perm中的類靜態屬性引用的對象,以及常量引用的對象
3、本地方法棧中JNI(Native方法)的引用的對象

所以jni層,C函數調用C函數傳遞jobject對象時,對象的引用會被作為參數壓入到本地方法棧中,會從本地方法棧(GC root的一種)產生引用,這麼就不會被gc了。同樣java層和jni層互相調用時,總會被GC root引用到,也不會被GC 回收了。

android 記憶體回收

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.