1. 程式人生 > >Java提高——Java的記憶體回收(2)

Java提高——Java的記憶體回收(2)

Java的記憶體洩漏

記憶體洩漏:程式執行過程中,不斷的分配記憶體空間,那些不再使用的記憶體空間應該即時回收,,從而保證系統可以再次使用這些記憶體。如果存在無用的記憶體沒有被回收,那麼就是記憶體洩漏。

垃圾回收機制

垃圾回收機制主要完成以下兩件事:

1、跟蹤並監控每個Java物件,當某個物件處於不可達狀態則回收該物件所佔用的記憶體

2、清理記憶體分配、回收過程中產生的碎片

垃圾回收的基本演算法

實際上,垃圾回收機制不可能實時監測到每個Java物件的狀態,因此當一個物件失去引用之後,它不會被立即回收,只有等垃圾回收執行時才會被回收。

垃圾回收的涉及演算法大致如下:

序列回收和並行回收:序列回收就是無論多少個CPU,始終只用一個執行垃圾回收操作;並行回收就是把整個垃圾回收工作分成多個部分供多個CPU負責,讓多個CPU並行回收,效率很高,複雜度增加,但是產生的碎片很多。

併發執行和應用程式停止:應用程式停止的垃圾回收方式會導致應用程式的暫停,併發執行垃圾回收的方式需要解決和應用程式的衝突問題,因此開銷比較大。

壓縮和不壓縮和複製:

    壓縮(標記壓縮):把所有活得物件搬到一起,將之前佔用得記憶體全部回收

    不壓縮(標記清除):只是回收記憶體,且回收回來得記憶體是不連續的,會有更多碎片。(且回收回來的記憶體塊分配更慢,無法解決碎片問題)

    複製:將所有物件複製到另一塊相同的記憶體中,不會產生記憶體碎片,但是需要複製資料和額外的記憶體。

現行的垃圾回收器用分代的方式來採用不同的回收設計。根據物件的生存時間長短,把堆記憶體分成3個代:

Yong(年輕代)、Old(老年代)、permanent(永久代)

堆記憶體分代回收

分代回收依據物件的生存時間的長短,然後根據不同代採取不同的垃圾回收策略。

採用“分代回收”的策略基於如下事實:

1、絕大多數的物件不會被長時間引用,這些物件在Yong期間就會被回收;

2、很老的物件和很新的物件之間很少存在相互引用。

一、Yong代

Yong代採用複製演算法,只需要遍歷那些處於不可達狀態的物件,而且物件的數量少,複製成本小,能充分發揮複製演算法的優勢

二、Old代

Old代垃圾回收具有如下兩個特徵:

1、Old代垃圾回收的執行頻率不會太高,因為很少有物件死掉

2、對每次Old代執行垃圾回收需要更長的時間來完成。

基於以上,通常採用標記壓縮演算法,避免複製Old代的大量物件,且不會大量產生碎片,比較划算。

三、Permanent代

Permanent代主要用於裝載Class、方法等資訊,預設64M,垃圾回收機制通常不會回收Permanent代中的物件。

常見垃圾回收器

1、序列回收器

對Yong代和Old代的回收都使用序列(只使用一個CPU),且執行期間會使程式暫停。Yong代採用串行復制演算法,Old代使用序列標記壓縮演算法。

2、並行回收器

Yong代與序列回收相似,只是啟用了多個CPU,多執行緒;Old代採用與序列回收相同的演算法,不管有幾個CPU都採用單執行緒、標記整理的方式進行回收。

3、並行壓縮回收器

4、併發標識-清理回收器(CMS)

記憶體管理小技巧

1、儘量使用直接量

如:String str = “123”;而不是String str = new String(“123”);

2、使用StringBuffer和StringBuilder進行字串連結

3、今早釋放無用物件

4、儘量少使用靜態變數

5、避免在經常呼叫的方法、迴圈中建立Java物件

6、快取經常使用的物件

7、儘量不要使用finalize方法

8、考慮使用SoftReference