JAVA回收機制與Android的OOM

這幾天做課件看了不少JVM相關的知識怕自己忘記。大部分理論知識都是來自網上其他博客的引用,我把自己想要重點記錄的記了下來。

                                                      

RAM隨機存取存儲器臨時存儲的地方,關機後數據消除,也叫主存。圖是網上找的,JVM的內存模型圖,Dalvik是一個特殊的JVM所以需要先從瞭解JVM開始。

我們需要了解虛擬內存這個概念。

虛擬內存概念:呈現出比實際擁有大得多的內存量,使得每個應用程序認爲自己擁有連續且可用的空間。

我來解釋下這段話64位系統中,理論尋址次數爲2∧64,實際的尋址次數爲2∧48。存數據是需要地址的,尋址的次數就等於虛擬內存的大小。虛擬地址會對應一個物理地址,但是這個物理地址並不連續。如果物理地址不夠用,就會進行交換空間操作把內存上釋放某些進程佔用但未使用的部分或者所有物理內存,被釋放的部分儲存在磁盤上

我看到過一個形象的比喻來說交換空間,一列火車從北京到上海,你只需要3公里的鐵路就可以辦到。

程序計數器:程序計數器是一塊很小的內存空間,它是線程私有的,可以認作爲當前線程的行號指示器。

Java棧(虛擬機棧):線程私有,生命週期與相同,就是我們平時說的棧,棧描述的是Java方法執行的內存模型。以幀爲單位出入,存儲局部變量,操作數棧,動態鏈接,方法返回地址等。

本地方法棧:執行調用C/C++的地方。

:Java虛擬機管理內存最大的一塊內存區域,因爲堆存放的對象是線程共享的,所以多線程的時候也需要同步機制。是一個完全二叉樹。

方法區:用於存儲已被虛擬機加載的類信息、常量、靜態變量,如static修飾的變量加載類的時候就被加載到方法區中。

本文不主要記錄內存模型,只是注意2個地方:

1.7之前運行常量池在方法區的永生代中,之後在堆中。

2.永生代在8被去除,改爲元空間。

元數據包括:class ,enum(枚舉),interface(接口),元數據

permgen去除原因:永久代中的元數據可能會隨着每一次Full GC發生而進行移動。並且爲永久代設置空間大小也是很難確定的,因爲這其中有很多影響因素。

數據類型分爲兩種

  概念 內存 使用 局部 全局
基礎數據類型(char,int,boolean等) 指向具體數值 直接分配內存 不能爲null 值和變量名都在棧 堆裏
引用數據類型(類,接口,數組) 指向地址 沒有內存,只有地址 可以爲null 實例在堆,地址在棧 堆裏

回收機制

可回收對象的判定方法

引用計數算法

每當有地方引用,計數器加一,引用失效減一,算法簡單,但是會出現兩個對象相互持有。如圖(其他博客那拿的)。

可達性分析算法

通過一些可以被當做GC Roots的對象,向下搜索,走過的路徑稱爲引用鏈。當對象沒有和引用鏈相連時,則說明可以回收。

                                             

可以當做GC Roots的對象

1.本地方法區JNI的引用對象;

2.方法區的常量對象,目前我只知道final這種形式的常量對象,還有別的可以告訴我一下;

3.方法區類靜態屬性的引用;

4.java虛擬棧的局部變量引用;

注:可達性分析算法中,不可達對象並非“非死不可”,有一個可以救贖的辦法,就是複寫finalize()方法。但是!!

複寫這個方法,不保證會執行完裏面的代碼。經過事實證明,執行完成率低,調用代價帶,極爲不推薦複寫!!

按照一個博主所說,這個方法是爲了讓C/C++程序員儘快適應JAVA所做出的妥協。

不太想詳細講的算法就直接把我做的PPT貼出來了。

所有算法都用到了標記清除算法,着重講一下現在用的最多的分代回收算法

首先分代回收算法不是一個單獨使用的算法,需要其他的算法配合使用。

                 

 Eden(伊甸園區):新生代區,用來分配創建新的對象,被劃分爲多個縣城本地分配的緩衝區,劃分後,JVM在對應線程緩衝區直接分配可以避免同步操作。

Survivor(存活區):有2個存活區稱爲to區和from區。To區開始爲空,開始GC後,Eden與From區把有用對象放進To區。然後會有一個頭部計數加一,等15次之後會進入老年區。To區與From區總會任意時刻總有一個空的。

Old Generation(老年區):裏面對象是垃圾概率很小,所以發生GC頻率會很低。

Minor GC:用於清理年輕態區域 Major

GC:清理老年代區域

Full GC:(完全GC)清理的是整個堆

GC發生時會有一個全線暫時停止操作,垃圾收集過程中,需要暫停應用所有線程,不過時間非常短。

OOM原因

Heap(堆)是由程序員自己來控制的,OOM是因爲android系統對Dalvik虛擬機的heap大小做了硬性限制,當JAVA進程申請空間超過這個數值時就會OOM(這個閾值因機型而異)。

程序發生OOM並不表示RAM不足,RAM充足情況也會OOM。

RAM目的是爲了更多應用能常駐在其中,這樣程序啓動不必每次都加載到內存,這樣啓動應用速度會更快。當RAM真的不足時,memory killer會殺死一些優先度低的進程。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章