深入理解java虚拟机(三)——垃圾收集算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Back_Light_F/article/details/81637660

话不多说,直接开始。

标记—清除算法:

最基础的算法就是标记—清除算法了。该算法分为两个阶段:标记、清除。

首先标记出需要回收的对象,在标记完成后统一回收掉所有被标记的对象。

由下图可知,该算法有两个主要缺点:一个是效率问题(标记和清除效率都不高);一个是空间问题(清除后产生大量的内存碎片),这会导致程序在以后运行过程中需要分配大对象时找不到足够的连续内存而不得不提前触发另一次垃圾收集动作。

复制算法: 

复制算法为了解决效率问题,将可用内存按容量划分为大小相等的两块,每次只使用其中一块。当这一块内存使用完了,就将还存活着的对象复制到另一块上面,然后再把之前使用过的内存空间一次清理掉。

这种算法的优点是简单高效,缺点也是显而易见的:一次只能使用一半的内存。

现在的商业虚拟机基本上采用这种收集算法来回收新生代。新生代中的对象98%都是朝生夕死的,所以不需要按照1:1来划分空间,而是将内存划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中的一块Survivor。当回收时,将Eden和Survivor还存活的对象一次性的拷贝到另一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot默认Eden和Survivor的比例为8:1。当Survivor不够用时。 需要依赖其他内存(老年代)进行分配担保。(Handle Promotion)

         内存的分配担保:如果另一块Survivor没有足够的空间存放上一次新生代收集下来的存活对象,这些对象将直接通过分配担保机制进入老年代。

标记—整理算法:

复制收集算法在对象存活率较高时就要执行较多的复制操作,效率会变低。

标记—整理算法的标记过程和“标记—清除算法”一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存:

分代收集算法:

这种算法根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。老年代中对象存活率高,没有额外的空间进行分配担保,就必须使用“标记—清理”或“标记—整理”算法来进行回收。

猜你喜欢

转载自blog.csdn.net/Back_Light_F/article/details/81637660
今日推荐