现在的位置: 首页 > 综合 > 正文

JVM垃圾收集算法

2017年06月10日 ⁄ 综合 ⁄ 共 1318字 ⁄ 字号 评论关闭

      java虚拟机JVM垃圾收集算法有四种:标记-清除算法、复制算法、标记-整理算法以及分代收集算法。

1、标记-清除算法

      这是JVM最基础的垃圾收集算法。如下图:

          

      该算法分为两个阶段:“标记”和“清除”。首先标记处所有需要回收的对象,然后统一清除被标记的对象。

      该算法,标记和清除两个阶段的效率不高。此外,回收后会产生大量的不连续的内存碎片,进一步会导致垃圾回收次数的增加。

2、复制算法

      为了解决标记-清除算法的效率问题,出现了复制算法,如下图:

          

      该算法的思想是将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这块的内存用完了,则将还存活的对象复制到另外一块内存上去,然后再把刚使用过的内存空间一次清理掉。从而达到了每次垃圾回收时只是针对其中一块,避免了产生内存碎片等情况。

      该算法的代价是只是使用了其中一本的内存,代价有点高。

      随着研究的不断发现,商业虚拟机在该算法中不断进行优化尝试。比如在HotSpot虚拟机中,新生代中Eden和Survivor的大小比例为8::1,因为新生代的对象需要回收的概率大(对象的生命周期短,存活率低),所以内存的可用率达到了90%(新生代分为:Eden和两块Survivor)。每次都是把Eden和Survivor中存活的对象拷贝到另一块Survivor中,然后清理掉Eden和Survivor空间。

3、标记-整理算法

      当复制收集算法面对的回收对象为存活率较高的情况时,要执行较多的复制操作,效率会变低。为了提高这些对象垃圾回收效率,充分利用可用内存,标记-整理算法出现了。如下图:

        

      该算法集成了标记-清除和复制收集算法的优点。第一个阶段仍是进行标记,第二个阶段是把所有存活的对象都向一端移动,按顺序排放,然后直接清理掉端边界意外的内存。该算法避免了标记-清除的内存碎片问题以及复制算法的空间问题。该算法适合于老年代对象的回收。

4、分代收集

      这是目前大多数虚拟机采用的垃圾回收算法。基于对象的生命周期划分为新生代、老年代以及持久代。比如新生代就采用复制收集算法,而老年代就采用标记-清除或者标记-整理算法。如下图:

          

      对于分代收集,虚拟机需要区分对象的分配年代,是放在新生代还是否放在老年代?。解决的办法是:jvm为每个对象定义了一个对象年龄计数器。如果对象在Eden出生并且经过第一次新生代GC(Minor GC)后仍然存活并且能被Survivor容纳,则该对象将被移动到另一块Survivor空间,并将对象年龄计数器加1。对象在Survivor区中每经历过一次Minor GC,年龄计数器就加1,当它的年龄达到设定的阈值(默认是15)时,则被移动到老年代中。阈值的设置通过参数-XX:MaxTenuringThreshold设置。

      当然,并不是一定达到阈值才被移动到老年代,为了适应复杂的情况,动态的判定对象年龄,虚拟机规定:如果Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,对象的年龄大于或者等于该年龄的对象就可以直接进入老年代,不必等到达到设定的阈值。

抱歉!评论已关闭.