JVM垃圾回收算法

91 阅读2分钟

内容整理来源《深入理解Java虚拟机》

标记-清除算法(Mark-Sweep)

  1. 首先标记出所有要回收的对象,在标记完成后统一回收所有被标记的对象。
  2. 缺点:
    • 空间上:产生大量的不连续的内存碎片,在给大对象分配内存时,容易因为没有足够的连续的内存而提前触发垃圾回收。
    • 效率上:标记、清除两个动作效率都不高。

复制收集算法(Copying)

  1. 将内存划分为相等的两块,每次仅使用一块内存。当一块内存用完了,就将存活的对象复制到另一块内存,并将已使用的内存一次性清除。
  2. 优点:内存分配时无需考虑内存碎片,只需移动堆顶指针,按顺序分配即可。实现简单、运行高效。
  3. 缺点:
    • 浪费了一半内存空间。
    • 存活对象较多时,复制操作效率低。
  4. 优化:

内存空间:因98%的新生代对象是“朝生暮死”,所以不需要按照1:1的比例划分内存,而是将内存划分为一块较大的Eden和两块较小的Survivor,每次使用一块Eden和一块Survivor。当回收时,将Eden和在使用的Survivor中存活的对象复制到空闲的Survivor上,然后将Eden和在使用的Survivor清除。HotSpot虚拟机默认Eden和Survivor的比例是8:1,意味着只有10%的空间会被浪费。当然我们无法保证每次活着的对象仅占用不超过10%的内存空间。当空闲的Survivor空间不够时,需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion)。

标记-整理算法(Mark-Compact)

  1. 基于标记-清除算法做了优化,将所有存活的对象都向一端移动,然后直接清理掉端边以外的内存。

分代收集算法(Generational Collection)

根据对象的生存周期将内存划分成几块,分别采用不同的收集算法。 一般把Java堆划分成新生代和老年代,新生代采用复制算法,老年代采用标记-清除或标记-整理算法。