JVM篇:虛擬機器的主角GC
一、GC是什麼?
垃圾回收器,可以理解為偉大的環衛工
二、為什麼偉大?
如圖:
簡單來說它能讓我們不用去繁瑣的釋放記憶體空間
三、那麼它是如何去判斷哪些是垃圾?哪些不是垃圾呢?
方法一:引用計數法
它的原理是:每次引用一個物件計數時+1,持有計數的引用物件退出作用域就-1
但是這樣做是有缺陷的,例如兩個物件互相引用,便會漏掉造成記憶體洩漏,對此有根搜尋法
來判斷它們的根是否不可達也會去清除,如下。
方法二:根搜尋演算法
它會對棧幀裡的區域性變數所引用的物件、方法區的靜態變數和常量所引用的物件,產生一個根路徑
當GC掃描時,會一級一級往上,如若根程序不可達,那麼判斷其為垃圾,這也就避免了物件之間相互呼叫產生的記憶體洩漏
四、垃圾怎麼清除?
方法一:標記清除法
它發現垃圾記憶體時,標記為可回收狀態,隨後再清空
但缺陷明顯!有空間碎片,即不是連續的記憶體區域,會造成效能過低,並且在清理過程中需要停止程式方法二:分段複製演算法
將可用的記憶體按容量劃分為大小相等的兩塊,每次只是用其中一塊,當使用的這塊記憶體用完了,就將還存活著的物件複製到另外一塊上面並且自動整理,然後把已使用過的記憶體空間一次清理完
缺點:浪費記憶體空間,如果物件存活率較高時要執行較多的複製操作,效率降低並且在清理過程中需要停止程式
方法三:標記整理演算法
將可回收的物件標記,然後將所有存活物件向一端移動排序,再對可回收物件進行清理
他的缺點也是效率不高,不僅要標記所有可回收物件,還需要整理存活物件物件的引用地址,效率來說可能連分段複製演算法都比不過並且在清理過程中需要停止程式
方法四:分代收集法
我們可以從圖中認為,整個堆被分為新生代與老年代,而新生代又被劃分為了三個,伊甸園(Eden)、From Survivor、 To Survivor
清理級別分為三個級別:第一級Minor GC(清理新生代)、第二級別Major GC(清理老年代)、第三級別Full GC(新老同時清理)
新建的物件會出現在新生區,然後經過GC不斷的清理,存活物件將會往右劃分,當存活次數一定時便會劃入老年代,新生代與老年代的區別在於,掃描頻率不一樣,左邊掃描頻率高,目的是合理利用資源,提高效能。
第一次Minor,存活物件會進入From區域,這時候判斷To是否 還有儲存空間,如果有,那麼再進行Minor級別的分段複製法,如果物件仍然存活,那麼進入To區域,jvm會自動設定它的年齡為1,當年齡為15時會進入老年區(年齡預設為15,當然也可以自己去設定),老年區也會有將較大的物件直接劃分到自己這塊區域,不是一定要通過新生代的。然後我們可以從圖中得知老年代的每次清理,使用的是標記-整理法。