1. 程式人生 > >GC垃圾回收機制

GC垃圾回收機制

如果 pin class 經驗 就會 第一個 分配 產生 有一個

JVM堆相關知識
為什麽先說JVM堆?
JVM的堆是Java對象的活動空間,程序中的類的對象從中分配空間,其存儲著正在運行著的應用程序用到的所有對象。這些對象的建立方式就是那些new一類的操作,當對象無用後,是GC來負責這個無用的對象(地球人都知道)。
JVM堆
(1) 新域:存儲所有新成生的對象
(2) 舊域:新域中的對象,經過了一定次數的GC循環後,被移入舊域
(3)永久域:存儲類和方法對象,從配置的角度看,這個域是獨立的,不包括在JVM堆內。默認為4M。

新域會被分為3個部分:1.第一個部分叫Eden。(伊甸園??可能是因為亞當和夏娃是人類最早的活動對象?)2.另兩個部分稱為輔助生存空間(幼兒園),我這裏一個稱為A空間(From sqace),一個稱為B空間(To Space)。


二、GC淺談
GC的工作目的很明確:在堆中,找到已經無用的對象,並把這些對象占用的空間收回使其可以重新利用.大多數垃圾回收的 算法思路都是一致的:把所有對象組成一個集合,或可以理解為樹狀結構,從樹根開始找,只要可以找到的都是活動對象,如果找不到,這個對象就是雕零的昨日黃 花,應該被回收了。
在sun 的文檔說明中,對JVM堆的新域,是采用coping算法,該算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。它開始時把堆分成一個對象面和多個空閑面,程序從對象面為對象分配空間,當對象滿了,基於 coping算法的垃圾收集就從根集中掃描活動對象,並將每個活動對象復制到空閑面(使得活動對象所占的內存之間沒有空閑洞),這樣空閑面變成了對象面,原來的對象面變成了空閑面,程序會在新的對象面中分配內存。

對於新生成的對象,都放在Eden中;當Eden充滿時(小孩太多 了),GC將開始工作,首先停止應用程序的運行,開始收集垃圾,把所有可找到的對象都復制到A空間中,一旦當A空間充滿,GC就把在A空間中可找到的對象 都復制到B空間中(會覆蓋原有的存儲對象),當B空間滿的時間,GC就把在B空間中可找到的對象都復制到A空間中,AB在這個過程中互換角色,那位客官說 了:拷來拷去,煩不煩啊?什麽時候是頭?您別急,在活動對象經過一定次數的GC操作後,這些活動對象就會被放到舊域中。對於這些活動對象,新域的幼兒園生 活結束了。新域為什麽要這麽折騰?起初在這塊我也很迷糊,又查了些資料,原來是這樣:應用程序生成的絕大部分對象都是短命的,copying算法最理想的 狀態是,所有移出Eden的對象都會被收集,因為這些都是短命鬼,經過一定次數的GC後應該被收集,那麽移入到舊域的對象都是長命的,這樣可以防止AB空 間的來回復制影響應用程序。實際上這種理想狀態是很難達到的,應用程序中不可避免地存在長命的對象,copying算法的發明者要這些對象都盡量放在新域 中,以保證小範圍的復制,壓縮舊域的開銷可比新域中的復制大得多(舊域在下面說)。對於舊域,采用的是tracing算法的一種,稱為標記-清除-壓縮收 集器,註意,這有一個壓縮,這是個開銷挺大的操作。垃圾回收主要是對Young Generation塊和Old Generation塊內存進行回收,YG用來放新產生的對象,經過幾次回收還沒回收掉的對象往OG中移動,對YG進行垃圾回收又叫做MinorGC,對 OG垃圾回收又叫MajorGC,兩塊內存回收互不幹涉。二、Gc 流程:
[older generation][survivor 1][survivor 2][eden]
*young generation=eden + survivor
1.當eden滿了,觸發young GC;
2.young GC做2件事:一,去掉一部分沒用的object;二,把老的還被引用的object發到survior裏面,等下幾次GC以後,survivor再放到old裏面。
3.當old滿了,觸發full GC。full GC很消耗內存,把old,young裏面大部分垃圾回收掉。這個時候用戶線程都會被block。

三、young generation比例越大,不一定最好。
將young的大小設置為大於總堆大小的一半時會造成效率低下。如果設置得過小,又會因為young generation收集程序不得不頻繁運行而造成瓶頸。

四、總結
從上面的推導可以得出很多結論,下面是前輩的經驗總結與自已的認識
1.JVM堆的大小決定了GC的運行時間。如果JVM堆的大小超過一定的限度,那麽GC的運行時間會很長。
2.對象生存的時間越長,GC需要的回收時間也越長,影響了回收速度。
3.大多數對象都是短命的,所以,如果能讓這些對象的生存期在GC的一次運行周期內,wonderful!
4.應用程序中,建立與釋放對象的速度決定了垃圾收集的頻率。
5.如果GC一次運行周期超過3-5秒,這會很影響應用程序的運行,如果可以,應該減少JVM堆的大小了。
6.前輩經驗之談:通常情況下,JVM堆的大小應為物理內存的80%。

GC垃圾回收機制