關於GC垃圾回收及其算法的一點思考

在學過java一些有關GC以及相關算法後,對一些概念以及GC與垃圾回收算法的關係有點混亂,覺得有必要好好總結一下了,雖然GC誕生的時間比java早,並且GC並不是java語言所獨有的,但垃圾收集機制是java語言的招牌能力,極大的提高了開發效率,並且成爲現代語言的標配,因此我們必須深入學習java的垃圾收集機制

1.什麼是GC,什麼是垃圾,爲什麼需要GC

GC是指垃圾回收機制,所謂垃圾是指在運行程序中沒有任何指針指向的對象

當一個對象不能再被複後續程序所引用到時,這個對象所佔用的內存空間就沒有存在的意義了,java虛擬機會不定時的去檢測內存中這樣的對象,然後回收這塊內存空間。這也是垃圾和GC的關係,一個java程序在運行之中是會不斷產生對象的,並且絕大多數對象生命週期很短,很容易變成垃圾佔用大量內存空間,並且這些空間會一直保留到應用程序結束

對於高級語言來說,如果不進行垃圾回收,內存遲早會被消耗完,這種情況下就非常有必要進行GC,垃圾回收除了釋放沒用的對象,還進行內存中內存碎片的清理(對應着垃圾回收算法中的標記-整理算法),以便將整理出來的內存分配給新的對象,沒有GC就不能保證程序的正常進行

2.GC採取分代收集算法執行垃圾回收

在我的博客垃圾收集算法-如何判定對象死亡中詳細闡述瞭如何判斷對象死亡,其中的可達性算法通過GC Roots按照從上至下的方式搜索被根對象集合所鏈接的對象是否可達,來判斷對象是否可以被回收,並且應用在標記-清除算法和標記-整理算法中的標記階段

標記-清除算法,標記-整理算法,標記-複製算法這三種算法各有優缺點,不能說它們中的哪一個是最好的算法,只有在合適的場景中發揮各自的優勢,分代收集算法應運而生

接着往下,我們都知道java對象的生命週期長短不一,絕大多數對象朝生夕死和熬過多次收集的難以消亡的對象,針對這一現象發展出兩個假說:

  • 弱分代假說
  • 強分代假說

這兩個假說共同奠定了多款垃圾收集器的的一致設計原則:垃圾收集器應該將java堆劃分成不同的區域,然後將回收對象根據其年齡分配到不同的區域中存儲,這就是分代收集理論

注意:在《Java虛擬機規範》中指出:所有的對象實例以及數組都應該在對上分配,僅僅是指出了堆因該存儲什麼,而沒有進一步將堆細分爲年輕代,老年代,Eden,Survivor區了,實際上,這些將堆更細緻的劃分是一部分垃圾收集器的設計風格而已,目的是根據不同生命週期的對象劃分出不同的內存區域,運用不同垃圾收集算法採取不同收集方式提高回收效率,因此並不是虛擬機實現的堆的內存佈局,更不是《Java虛擬機規範》中堆Java堆的劃分

在Java堆中劃分出不同區域之後,垃圾收集器可以每次只回收其中一個或某些部分的區域,也就產生了Minor GC,Major GC,Full GC這樣的回收類型的劃分
如上所述,HotSopt虛擬機也是基於分代的概念,其GC所使用的內存回收算法必須結合年輕代和老年代各自的特點

  • 年輕代的特點這裏就不贅述了,按照分代思想,由於此區域對象生命週期短暫,存活率低,回收頻繁,那麼標記-複製算法在這種情況下可以發揮出它的優勢,因此很適用於年輕代的垃圾回收,且該算法的內存利用率不高的問題也被hotspot中的兩個survivor涉及所緩解
  • 對於老年代,該區域較大,對象生命週期長,存活率搞,回收頻率較低,在這種情況下複製算法顯然不適用,因此採取的是標記清除或者標記清除和標記整理的混合實現

總結的話來說就是:分代思想被現有的虛擬機廣泛使用,幾乎所有垃圾回收器都區分新生代和老年代,不同區域採取不同收集方式,根據分代運用不同算法

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