jvm垃圾回收

垃圾回收狀況:java

一、    對象沒有引用算法

二、    做用域發生未捕獲異常spa

三、    程序在做用域正常執行完畢orm

四、    程序執行了System.exit()對象

五、    程序發生意外終止(被殺進程等)進程

垃圾回收算法:圖片

1引用計數器算法內存

JDK1.2以前,使用的是引用計數器算法,即當這個類被加載到內存之後,就會產生方法區,堆棧、程序計數器等一系列信息,當建立對象的時候,爲這個對象在堆棧空間中分配對象,同時會產生一個引用計數器,同時引用計數器+1,當有新的引用的時候,引用計數器繼續+1,而當其中一個引用銷燬的時候,引用計數器-1,當引用計數器被減爲零的時候,標誌着這個對象已經沒有引用了,能夠回收了!這種算法在JDK1.2以前的版本被普遍使用,作用域

可是隨着業務的發展,很快出現了一個問題虛擬機

當咱們的代碼出現下面的情形時,該算法將沒法適應

a)         ObjA.obj = ObjB

b)         ObjB.obj - ObjA

                 這樣的代碼會產生以下引用情形 objA指向objB,而objB又指向objA,這樣當其餘全部的引用都消失了以後,objAobjB還有一個相互的引用,也就是說兩個對象的引用計數器各爲1,而實際上這兩個對象都已經沒有額外的引用,已是垃圾了。

               


二、              根搜索算法

                   根搜索算法是從離散數學中的圖論引入的,程序把全部的引用關係看做一張圖,從一個節點GC ROOT開始,尋找對應的引用節點,找到這個節點之後,繼續尋找這個節點的引用節點,當全部的引用節點尋找完畢以後,剩餘的節點則被認爲是沒有被引用到的節點,即無用的節點。

 



 

 

目前java中可做爲GC Root的對象有

一、    虛擬機棧中引用的對象(本地變量表)

二、    方法區中靜態屬性引用的對象

三、    方法區中常量引用的對象

四、    本地方法棧中引用的對象(Native對象)

瞭解了JVM是怎麼肯定對象是「垃圾」以後,進入正題,讓咱們來看看垃圾回收的算法。

1.標記—清除算法(Mark-Sweep

標記—清除算法兩個階段:「標記」和「清除」。在標記階段,肯定全部要回收的對象,並作標記。清除階段緊隨標記階段,將標記階段肯定不可用的對象清除。

標記—清除算法是基礎的收集算法,標記和清除階段的效率不高,並且清除後回產生大量的不連續空間,這樣當程序須要分配大內存對象時,可能沒法找到足夠的連續空間。

垃圾回收前:


垃圾回收後:


綠色:存活對象 紅色:可回收對象 白色:未使用空間

2.複製算法(Copying

複製算法是把內存分紅大小相等的兩塊,每次使用其中一塊,當垃圾回收的時候,把存活的對象複製到另外一塊上,而後把這塊內存整個清理掉。

複製算法實現簡單,運行效率高,可是因爲每次只能使用其中的一半,形成內存的利用率不高。如今的JVM用複製方法收集新生代,因爲新生代中大部分對象(98%)都是朝生夕死的,因此兩塊內存的比例不是1:1(大概是8:1)

垃圾回收前:


垃圾回收後:


綠色:存活對象 紅色:可回收對象 白色:未使用空間

3.標記—整理算法(Mark-Compact

標記—整理算法和標記—清除算法同樣,可是標記—整理算法不是把存活對象複製到另外一塊內存,而是把存活對象往內存的一端移動,而後直接回收邊界之外的內存。

標記—整理算法提升了內存的利用率,而且它適合在收集對象存活時間較長的老年代。

垃圾回收前:


垃圾回收後:


綠色:存活對象 紅色:可回收對象 白色:未使用空間

4.分代收集(Generational Collection

分代收集是根據對象的存活時間把內存分爲新生代和舊生代,根據個代對象的存活特色,每一個代採用不一樣的垃圾回收算法。新生代採用標記—複製算法,old採用標記—整理算法。

垃圾算法的實現涉及大量的程序細節,並且不一樣的虛擬機平臺實現的方法也各不相同。上面介紹的只不過是基本思想。

相關文章
相關標籤/搜索