參考 《深入理解Java虛擬機 JVM高級特性與最佳實踐》 3.3節
1.標記-清除算法
標記-清除算法
主要不足有兩個:
- 效率問題:標記和清除兩個過程的效率都不是很高
- 空間問題:標記清除后會產生大量內存碎片,會導致之后有較大對象需要分配時找不到足夠大的連續內存而又出發垃圾回收動作。
2.復制算法
復制算法
- 復制算法將內存分成了大小相等的兩塊,每次只使用其中的一塊。當這塊內存用完了,觸發垃圾回收,就將這塊內存中還活著的對象復制到另一半內存上,這個時候是不用整理的,直接一個一個推進去即可,這樣就不用考慮內存碎片的問題了。這種算法的代價是將內存縮小了一半,代價太大了。
- 商業虛擬機的做法是把內存分為一塊較大的Eden(伊甸園,大概就是指沒有"殺戮"的樂園的意思吧)空間,和兩塊較小的Survivor(就是存活下來的那些對象)空間(8:1:1)。使用的時候啟用Eden空間和一塊Survivor1空間,回收的時候把這兩塊空間還存活的對象(Survivor)復制到剩余的那塊Survivor2空間上去,接著清空剛剛使用的Eden空間和Survivor1空間,然后下一輪使用Eden空間和Survivor2空間,Survivor1作為收集存活對象的區域,往復循環。
- 為什么上圖中的復制算法只使用了兩塊內存,而商業虛擬機使用了三塊內存呢?剛開始還覺得很奇怪,覺得奇怪但是又找不出來到底哪里不對。是這樣的,如果是像上圖中那樣兩塊內存的話,當第一輪回收后,存活的對象都在Survivor區域后,下一輪,這個Survivor區域就要當做Eden來使用了,如果按8:2的比例來分配的話,那此時可使用的內存就??們却娴?0%了,這不現實,所以采用了三塊內存的方式,Survivor1和Survivor2輪流作為Eden的一部分來使用。
- 因為不能保證每次存活下來的對象都在10%以下,如果出現多余10%的對象存活下來了,那就需要依賴其他內存(這里指老年代)進行分配擔保。多余10%的那部分對象會通過分配擔保機制進入老年代。
3.標記-整理算法
-
標記整理算法跟標記刪除算法大致上差不多,就是比標記刪除算法多了個整理的過程,即在清理前把或者的對象整理到一起,這樣清理起來效率會高一點。
標記-整理算法
4.分代收集算法
- 分代算法也沒有什么新的思想,就是對堆中的對象進行分代,然后對老年代使用標記-整理算法,對新生代使用復制算法。
- 老年代存活率較高,新生代存活率較低。
5.暫時我自己的理解
- 一個對象只要逃過它面臨的第一次垃圾收集后,它就成為老年代的成員了
- 被回收的都是大量的臨時對象吧