JVM 垃圾回收算法

在JAVA语言中可以作为GC Root的对象包括下面几种:

  局部变量表中引用对象

  静态属性引用的对象

  方法区常量 引用的对象

  本地方法栈中(JNI)引用的对象.

永生代中垃圾收集主要回收两部分内容:废弃常量和无用的类. 

在大量使用反射、动态代理、CGLib等ByteCode框架、动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

垃圾回收算法:

  1. 标记情书算法(Mark-Sweep): 最基础的收集算法, 会有两个问题: 标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片
  2.  复制算法; 特点:实现简答高效, 但会浪费一部分内存, HotSpot虚拟机默认Eden,Survivor的大小比例是8:1,这样只有10%的空间被"浪费"
  3. 标记整理算法: 针对老年代对象存货效率较高, 又不想浪费空间设计了本算法:  与标记清除算法相似, 但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存..
  4. 分代收集算法: 根据对象存活周期将内存划分为几块: 一般是分为新生代和老年代. 新生代每次都有大量对象死去,所以使用复制算法, 老年代对象存活率高, 使用标记整理算法.

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现.

Serial收集器:

是虚拟机运行在Client模式下的默认新生代收集器, 

特点: 单线程收集器, 它工作时会暂停所有其他线程, 真正实现"Stop the world",

优点: 简单高效,尤其是放在client端.

ParNew收集器

ParNew收集器除了多线程收集之外,其他与Serial收集器相比并没有太多创新之处,但它却是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作,

ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境中都不能百分之百地保证可以超越Serial收集器。当然,随着可以使用的CPU的数量的增加,它对于GC时系统资源的有效利用还是很有好处的。它默认开启的收集线程数与CPU的数量相同,在CPU非常多(譬如32个,现在CPU动辄就4核加超线程,服务器超过32个逻辑CPU的情况越来越多了)的环境下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

 

Parallel Scavenge收集器

Parallel Scavenge收集器是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器, 是吞吐量优先的收集器.

吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

Serial Old收集器

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法

这个收集器的主要意义也是在于给Client模式下的虚拟机使用。如果在Server模式下,那么它主要还有两大用途:一种用途是在JDK 1.5以及之前的版本中与Parallel Scavenge收集器搭配使用[1],另一种用途就是作为CMS收集器的后备预案.

Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器是在JDK 1.6中才开始提供的,

 

CMS(Concurrent Mark Sweep)收集器

是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上.CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,

整个过程分为4个步骤,包括:

  1. 初始标记(CMS initial mark) :  会stop the world, 只从GCRoot标记第一层
  2. 并发标记(CMS concurrent mark)
  3. 重新标记(CMS remark):会stop the world, 主要是为了修正并发标记时,用户对象位置的修改.
  4. 并发清除(CMS concurrent sweep)

 不足:

  1. 对CPU资源敏感, 占用一部分资源.;
  2. 无法处理浮动垃圾. 
  3. 因为是标记清理算法,所以会产生碎片.

 

 G1 收集器:

它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。

 

如果不计算维护Remembered Set的操作,G1收集器的运作大致可划分为以下几个步骤:

  1. 初始标记(Initial Marking)
  2. 并发标记(Concurrent Marking)
  3. 最终标记(Final Marking)
  4. 筛选回收(Live Data Counting and Evacuation)

 

ZGC收集器: 

JAVA 11 新GC收集器.


原文地址:https://www.cnblogs.com/snow-man/p/10552579.html