04-jvm-GC算法-算法理论

垃圾收集算法

标记-清除算法

image

  • 标记清除算法是最基础的收集算法,为了解决引用计数法的问题而提出的,他使用了根集的概念,
  • 分为“标记”和“清除”两个阶段:首先标记出所须要回收的对象,在标记完成后,统一回收掉全部被标记的对象,它的标记过程其实就是前面的跟搜索算法中判断垃圾对象的标记过程
  • 之因此说它是最基础的收集算法,是由于后续的收集算法都是基于这种思路并对其缺点进行改进而获得的 。
    image
优势:
  • 不须要进行对象的移动,而且仅对不存活的对象进行处理,在存活对象比较多的状况下极为高效
缺点
  • 标记和清除的过程效率都不高:这种方法须要使用一个空闲列表来记录全部的空闲区域及大小
  • 标记清除后,会产生大量不连续的内存碎片:虽然空闲区域的大小是足够的,但却可能没有一个单一区域可以知足此次分配所需的大小,所以本次分配仍是会失败(在Java中就是一次OutOfMemoryError)不得不触发另外一次垃圾收集动做
标记-整理算法 又称之:标记-压缩算法

image

  • 该算法标记过程与标记-清除算法中的标记过程一致,可是对标记过程后的垃圾对象处理状况不一样
  • 它不是直接对可回收对象进行清理,而是让全部的对象都向一端移动,而后清除掉端边界之外的内存
  • 在基于标记-整理算法的收集器的实现中,通常增长句柄和句柄表
    image
优势
  • 通过整理后,新对象分配只须要经过指针碰撞便能完成
  • 使用这种方法空闲区域的位置始终是可知的,也不会再由碎片的问题
缺点
  • GC的暂停时间会加长,由于须要将全部的对象都拷贝到一个新的地方去,还得更新他们的引用地址
复制算法

image

  • 该算法的提出是为了解决句柄的开销和堆碎片的垃圾回收
  • 他将内存按照容量分为大小相等的两块,每次只使用其中一块(对象面),当这一块的内存用完了,就将该快还存活的对象复制到另外一块的内存上面(空闲面),而后再把已经使用过的内存空间清理掉
  • 复制算法比较适合新生代,在老年代中,对象存活率比较高,若是执行较多的复制操做,效率将会下降,因此老年代通常会选用其余的算法,如:标记-整理算法
  • 如今的商业虚拟机都采用这种收集算法来回收新生代,可是并非将新生代划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象一次性复制到另外一块 Survivor 空间上,最后清理 Eden 和使用过的那一块 Survivor。
  • HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90%。若是每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时须要依赖于老年代进行分配担保,也就是借用老年代的空间存储放不下的对象

image

优势
  • 标记阶段和复制阶段能够同时进行
  • 每次只对一块内存进行回收,运行高效
  • 只须要必定栈顶指针,按照顺序分配内存便可,实现简单
  • 内存回收的时候,没必要考虑内存碎片
缺点
  • 须要一块能容纳下全部存活对象的额外内存空间,所以,可一次性分配的最大内存缩小了一半
分代收集
  • GC分代的基本假设:绝大部分对象的生命周期都很是短暂,存活时间短。算法

  • “分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就能够根据各个年代的特色采用最适当的收集算法指针

  • 在新生代中,每次垃圾收集时都发现有大批对象死去,只有少许存活,那就选用复制算法,只须要付出少许存活对象的复制成本就能够完成收集orm

  • 老年代中由于对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。cdn

    若是说收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现对象

相关文章
相关标签/搜索