天天看點

JavaGC垃圾處理

java的gc一般是在jvm的堆上進行的,java的堆中存放了大量的對象執行個體,是以javagc也叫gc堆。

java将記憶體區劃分為:

新生代(young generation/new)

    eden space

    from survivor/survivor 0

    to survivor/survivor 1

老年代(tenured generation/old)

永久代(一般指方法區和常量池,一般情況下永久代在虛拟機運作時就能确定大小的,但是一些架構可能會動态生成類資訊就會導緻永久代越來越大)

新生代要如此劃分是因為新生代使用的gc算法是複制收集算法。這種算法效率較高,而gc主要是發生在對象經常消亡的新生代,是以新生代适合使用這種複制收集算法。由于有一個假設:在一次新生代的gc(minor gc)後大部分的對象占用的記憶體都會被回收,是以留存的放置gc後仍然活的對象的空間就比較小了。這個留存的空間就是survivor space:from survivor或to survivor。這兩個survivor空間是一樣大小的。例如,新生代大小是10m(xmn10m),那麼預設情況下(-xx:survivorratio=8),eden space 是8m,from和to都是1m。

在new一個對象時,先在eden space上配置設定,如果eden space空間不夠就要做一次minor gc。minor gc後,要把eden和from中仍然活着的對象們複制到to空間中去。如果to空間不能容納minor gc後活着的某個對象,那麼該對象就被promote到老年代空間。從eden空間被複制到to空間的對象就有了age(年齡)=1。此age=1的對象如果在下一次的minor gc後仍然存活,它還會被複制到另一個survivor空間(如果認為from和to是固定的,就是又從to回到了from空間),而它的age=2。如此反複,如果age大于某個門檻值(-xx:maxtenuringthreshold=n),那個該對象就也可以promote到老年代了。

如果survivor空間中相同age(例如,age=5)對象的總和大于等于survivor空間的一半,那麼age>=5的對象在下一次minor gc後就可以直接promote到老年代,而不用等到age增長到門檻值。

在做minor gc時,隻對新生代做回收,不會回收老年代。即使老年代的對象無人索引也将仍然存活,直到下一次full gc。

深入了解javagc機智可參考文章:http://blog.csdn.net/initphp/article/details/30487407