JVM中垃圾收集之复制算法

一、复制算法的一般过程

将内存平均分成A、B两块:

1. 新生对象被分配到A块中未使用的内存当中。当A块的内存用完了, 把A块的存活对象对象复制到B块。

2. 清理A块所有对象。

3. 新生对象被分配的B块中未使用的内存当中。当B块的内存用完了, 把B块的存活对象对象复制到A块。

4. 清理B块所有对象。

5. goto 1。

优点:简单高效。

缺点:内存代价高,有效内存为占用内存的一半。

 二、复制算法的优化(对内存使用率的优化)

对复制算法进一步优化:使用Eden/S0/S1三个分区

平均分成A/B块太浪费内存,采用Eden/S0/S1三个区更合理,空间比例为Eden:S0:S1==8:1:1,有效内存(即可分配新生对象的内存)是总内存的9/10。 

算法过程:

1. Eden+S0可分配新生对象;

2. 对Eden+S0进行垃圾收集,存活对象复制到S1。清理Eden+S0。一次新生代GC结束。

3. Eden+S1可分配新生对象;

4. 对Eden+S1进行垃圾收集,存活对象复制到S0。清理Eden+S1。二次新生代GC结束。

5. goto 1。 

默认Eden:S0:S1=8:1:1,因此,新生代中可以使用的内存空间大小占用新生代的9/10。之所以不直接分成两个区,一个区占9/10,另一个区占1/10,可作出如下解释

1.S0与S1的区间明显较小,有效新生代空间为Eden+S0/S1,因此有效空间就大,增加了内存使用率

2.有利于对象代的计算,当一个对象在S0/S1中达到设置的XX:MaxTenuringThreshold值后,会将其分到老年代中,设想一下,如果没有S0/S1,直接分成两个区,该如何计算对象经过了多少次GC还没被释放,可以在对象里加一个计数器记录经过的GC次数,或者构建一张映射表记录对象和GC次数的关系,但是这样会扫描整个新生代中的对象,而有了S0/S1我们就可以只扫描S0/S1区就可以了。

发布了19 篇原创文章 · 获赞 0 · 访问量 255

猜你喜欢

转载自blog.csdn.net/wangqsse/article/details/105110868
今日推荐