垃圾回收算法
常见的垃圾回收算法有
- 标记-清除算法
- 标记-复制算法
- 标记-整理算法
标记-清除算法
该算法分为两个阶段,标记
和清除
- 标记:标记出所有需要回收的对象,或者标记处所有不需要回收的对象
- 清除:将需要回收的对象从内存中回收
使用标记-清除算法进行垃圾回收,会有几个缺点
- 效率不稳定,随着对象的增多,标记的效率会越来越低
- 内存碎片,由于只是将内存中的部分垃圾对象直接回收,没有对内存进行整理,在执行垃圾回收后,会产生大量的不连续的内存空间,接下来在新的对象分配时,可能很快就因为没有
足够大的连续的
内存空间来分配导致触发垃圾回收
标记-复制算法
常被称为复制算法
该算法将整个内存分为大小相等的两部分,每次分配对象时只用其中一块,当这块内存快用完时,对其进行回收,把这块内存中的所有的存活对象标记出来,然后复制到另一块未被使用的内存中去
使用标记-复制算法不会产生大量的内存碎片,但是它也有自己的缺点
- 内存使用率低,每次只使用整个内存的一半
- 当内存中存活对象较多时,复制效率较低
为了解决这个问题,在部分虚拟机,如HotSpot,对采用标记-复制算法的新生代做如下处理
- 将新生代划分为Eden区、SurvivorTo区、SurvivorFrom区
- E:Sto:Sfrom = 8:1:1
- 新对象优先分配在Eden区,发生MinorGC后,如果S区能够放下,就复制到S区
- 下次GC时,如果另一个S区能够放下当前存活的所有对象,就把S+E区的对象都复制到该S区,然后清空S和E区
- 如果S区中无法放下所有的存活对象,还会触发虚拟机的
空间分配担保机制(handle promotion)
,这个机制的主要作用就是,可以将新生代S区放不下的对象直接放入老年代
这样,内存的使用率就从50%上升到了90%,因为在新生代中,绝大多数的对象都是可以被快速回收的,甚至熬不过一轮GC
标记-整理算法
该算法在标记完存活对象后,会将所有的存活对象移动到内存的一侧,然后直接对另一侧内存进行回收
使用该算法进行垃圾回收,不会产生任何内存碎片,因为它对内存进行了整理
该算法的缺点
- 因为需要移动对象,所以其耗时会比不移动对象的算法(如,标记-清理)大