java gc總結


gc主要工作於java堆(包含新生區Young Generation及年老區Old Generation),方法區(永久區Permanent Generation 1.7-)
堆主要放活動對象,其中:
新生區分為eden,to survivor, from survivor,大小默認為8:1:1
剛剛new的對象會放在新生區(其實是放eden),每次gc后還存活會將其存活計數器+1,當存活數達到15次左右,置入年老區。
方法區就比較復雜了,包括類加載器,常量池等等,主要是類的信息(即加載類時需要加載的信息,包括版本、域、方法、接口等信息),靜態變量。
a.gc算法:
(1)復制算法(用於新生區):
eden,to survivor, from survivor這里簡稱a,b,c;回收過程如下
(a)對象不斷地產生...放入a,活動區為a
(b)a滿,根據root算法找出有用對象放入b(存貨計數+1);清空a;活動區為a,b
(c)循環上一步,直到a,b都滿
(d)對a,b都執行查找,將有用對象放入c;清空a,b;活動區為a,c
(e)這時每次a滿,改為放c,a,c滿,gc,然后改為使用a,b,如此類推。
復制算法適用於小量對象,因為復制會耗費相當的空間,復制后一並清除的做法好處是快速而不會產生碎片空間,通過不斷切活動區保證內存區可用。
需要注意的是如果大對象放不下b或者c,直接放年老區;上面提到的存貨計數達到一定程度也會移到年老區。
(2)標記-清掃算法(用於年老區,現在一般不用了):
找出所有不可達對象,並標記;標記完成后,一次性清除;會產生碎片空間,需要增加整理這一步。
(3)標記-整理算法(用於年老區,G1收集器以此為據):
可以說是上一算法的改進,先標記需要回收的對象,但是不會直接清理那些可回收的對象,
而是將存活對象向內存區域的一端移動,然后清理掉端以外的內存。
(4)gc一般不光顧永久區,故沒有特別的算法,永久區的回收一般是:
(a)常量池中的常量,常量如果沒有被引用則可以被回收
(b)無用的類信息(同時滿足以下條件):
<1>類的所有實例都已經被回收了
<2>加載類的ClassLoader已經被回收
<3>類對象的class對象沒有被引用(即沒有通過反射引用該類的地方)
b.gc的步驟概念
Minor GC : 會清理年輕代的內存,主要是eden滿觸發
Major GC : 清理老年代,一般由Minor GC觸發
Full GC  : 清理堆空間,如果Major GC沒法解決,直接清理所有空間,如果還是無法分配空間,則報內存溢出
很多時候Full GC其實是執行了Minor GC+Major GC。
c.新版本jdk對方法區的更改
(1)1.8+取消了永久區Permanent Generation,改為元空間 Metaspace,兩者都是對方法區的一種實現
元空間在本地內存,不在jvm內存中,默認情況下,元空間的大小僅受本地內存限制,但可以通過以下參數來指定元空間的大小:
-XX:MetaspaceSize,初始空間大小,達到該值就會觸發垃圾收集進行類型卸載,同時GC會對該值進行調整:
如果釋放了大量的空間,就適當降低該值;
如果釋放了很少的空間,那么在不超過MaxMetaspaceSize時,適當提高該值。
-XX:MaxMetaspaceSize,最大空間,默認是沒有限制的。
除了上面兩個指定大小的選項以外,還有兩個與 GC 相關的屬性:
-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空間容量的百分比,減少為分配空間所導致的垃圾收集
-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空間容量的百分比,減少為釋放空間所導致的垃圾收集
用法:java -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m class
(2)String常量池從永久代移到了堆中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM