jvm - 垃圾回收咱們知道了哪些類是須要清除的,那在java虛擬機中,他有哪些垃圾收集算法呢?java
標記-清除算法就是,先標記哪些對象是存活的,哪些對象是能夠回收的,而後再把標記爲可回收的對象清除掉。從下面的圖能夠看到,回收後,產生了大量的不連續的內存碎片,若是這個時候,有一個比較大的對象進來,卻沒有一個連續的內存空間給他使用,又會觸發一次垃圾收集動做。
算法
複製算法是經過兩個內存空間,把一方存活的對象複製到另一個內存空間上,而後再把本身的內存空間直接清理。
標記後,此時狀況以下:
而後再把左邊的存活對象複製到右邊:
複製完後,再清理本身的內存空間:
右邊的空間開始回收,再複製到座標,如此往復。這樣就可讓存活的對象緊密的靠在一塊兒,騰出了連續的內存空間。
缺點就是空間少了一半,這少了一半的空間用於複製存活的對象。可是在實際過程當中,大部分的對象的存活時間都很是短,也就是說這些對象均可以被回收的。好比說左邊有100M空間,可是隻有1M的對象是存活的,那咱們右邊就不須要100M來存放這個1M的存活對象。所以咱們的新生代是分紅3個內存塊的:Eden空間、From Survivor空間、To Survivor空間,他們的默認比例是8:1:1。也就是說,日常的時候有Eden+Survivor=90M可使用,10M用於存放存活對象(假設100M空間)。這個算法在jvm - 堆內存分配的對象優先在Eden分配中提過了。segmentfault
除了新生代,老年代的內存也要清理的,可是上面的算法並不適合老年代。由於老年代對象的生命週期都比較長,那就不能像新生代同樣僅浪費10%的內存空間,而是浪費一半的內存空間。
標記-整理與標記-清除都是先標記哪些對象存活,哪些對象能夠回收,不一樣的是他並無直接清理可回收的對象,而是先把存活的對象進行移動,這樣存活的對象就緊密的靠在一塊兒,最後才把垃圾回收掉。
回收前,存活對象是不連續的。
回收中,存活對象是連續的。
回收後,回收垃圾對象。
jvm
針對新生代,Minor GC觸發的緣由就是新生代的Eden區滿了,因此爲了減小Minor GC,咱們新生代的內存空間不要過小。若是說咱們給新生代的內存已經到達機器了極限了,那隻能作集羣了,把壓力分擔出去。
老年代的垃圾回收速度比新生代要慢10倍,因此咱們也要儘可能減小發生Full GC。
jvm - 堆內存分配中咱們提到了幾種進入老年代的方式,咱們看看這些是怎麼處理的:性能
上面的方法,既有加大新生代的內存空間,也有加大Survivor空間,實時上,怎麼優化,須要根據咱們的實際場景來看,JVM的優化並無銀彈。優化