GC的前世今生

java與C++之間又一堵由內存動態分配和垃圾收集技術所圍成的“高牆”,牆外面的人想進去,牆裏面的人想出來。

                                                                                                                              --------<<深入理解java虛擬機>>

 

C/C++ 中主要由用戶程序代碼來回收分配的內存,不存在無用的對象的篩選過程,效率上比垃圾回收機制更勝一籌。

java語言的一些性能上的劣勢都是爲了換取開發效率。

 

 

回收靠誰來做?  ----- > GC

什麼是GC?

Garbage Collection  垃圾收集(顧名思義,回收垃圾,不需要的對象)

 

GC要完成的事情:

1,哪些內存需要回收?

2,什麼時候回收?

3,如何回收?

 

GC關注的區域:

 

既然GC關注堆,我們就要先了解堆

新生代的比例   8:1:1  

 

無用的對象回收,有用的對象存活,那麼如何判斷對象是否存活?

如上圖:

GC ROOTS 到object1 ,object2,object3,object4有通路,即對象可達,則對象存活

GC ROOTS 到object5 ,object6,object7沒有通路,即對象不可達,則判定爲可回收的對象

 

垃圾收集算法

1,標記-清除算法

出現的最早

什麼叫標記,怎麼標記 ?    ----- >  通過GC ROOTS的可達性分析對需要回收的對象做標記

什麼叫清除?                         ----- >  統一清除(回收)所有被標記的對象

 

不足之處

效率問題 :兩次掃描耗時嚴重,標記和清除兩個過程本身的效率也都不高

空間問題:標記清除後會產生大量不連續的內存碎片

 

2,複製算法

爲了解決效率問題,複製算法橫空出世

實現簡單 運行高效 內存空間利用率低

 

3,標記-整理算法

 

分代收集算法
新生代:複製算法 

老年代:標記-清除算法    標記-整理算法

把堆分爲新生代和老年代 ,這樣就可以根據各個年代的特點採用最適當的收集算法。

 

設計時,對象儘量不要進入老年代 ,而是使我們的對象儘量在新生代回收掉(最理想的狀態下,所有的對象都不要進入老年代)

新生代 minor GC

老年代 major GC 比新生代慢十倍

 

垃圾收集算法和垃圾收集器有什麼關係?

垃圾收集算法是理論,垃圾收集器是垃圾收集算法的實現。

 

垃圾收集器

Serial

ParNew

Serial Old

Parallel Old

CMS

G1

垃圾收集器之間的連線表示搭配使用

目前流行的是ParNew 和 CMS的搭配使用

 

內存分配與回收的策略

GC是回收對象,那對象的創建和內存的分配是怎樣一個過程?

虛擬機爲新生對象分配內存,對象所需內存的大小在類加載完成後便可以完全確定

分配內存時有兩種情況:

1)java堆中的內存是規整的

什麼叫規整?----->  所有用過的內存放在一邊,空閒的內存放在另一邊,中間放着指針作爲分界點的指示器

上述分配方法稱   “指針碰撞”
 

指針可以看作是一個內存空間地址的偏移量

 

2)java堆中的內存不是規整的

已使用的內存和空閒的內存相互交錯,必須維護一個列表,記錄哪些內存塊可以用

在分配時從列表中找到一塊足夠大的空間劃分給對象,並更新列表上的記錄。

上述分配方式稱“空閒鏈表”(Free List)

 

指針碰撞  多線程併發競爭同一塊內存空間問題

如果兩個線程在同一塊空間申請空間 (併發情況並不是線程安全的)

如何解決上述問題?

法一:

jvm採用CAS  保證更新操作的原子性  實現同步

法二:

TLAB Thread Local Allocation Buffer 本地線程分配緩衝

棧上分配

避免同步 線程分配的空間不宜過大

每個線程都有自己的一小塊內存,哪個線程要分配內存,直接在自己的TLAB上分配

 

對象優先在Eden區分配

Eden區空間不夠,觸發Minor GC(針對新生代的GC)

 

 大對象直接進入老年代

-XX:PretenureSizeThreshold=3145728 3M

上述jvm參數 表示有超過3MB的對象會直接在老年代分配

 

長期存活的對象直接進入老年代

對象如果從Eden區經過一次Minor GC到Survivor區,age=1

在Survivor區沒熬過一次Minor GC,age++

設置晉升老年代年齡閾值

-XX:MaxTenuringThreshold=15

age=15時,進入老年代

 

動態對象的年齡判定

相同年齡所有對象的大小總和 > Survivor空間的一半

年齡大於或等於該年齡的對象就可以直接進入老年代,無需考慮MaxTenuringThreshold設置的閾值

 

空間分配擔保

Minor GC 之前檢查 老年代最大可用連續空間是否>新生代所有對象總空間

 

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