钻牛角尖系列之JVM(三)—垃圾收集器 客官°小女子只卖身不卖艺 2022-07-13 04:27 107阅读 0赞 **前面介绍了几种垃圾收集算法,其实也就是垃圾收集的方法,今天来说下具体的实现-------垃圾收集器。** **![Center][]** **上面这张图是1.7版本14之后的HotSpot虚拟机中所使用到的所有虚拟机。有连线说明可以一起工作。** **一:Serial收集器(复制算法)** **它是一款古老的单线程的垃圾收集器,在它执行垃圾收集时,不仅仅只会使用一个CPU或一个线程去完成垃圾回收,而且它工作时** **会停止所有的工作线程,直到它完成垃圾收集。这个就是“Stop The World”,但是用户体验不好。下面是它结合SerialOld收集** **器的工作示意图:** **![Center 1][]** **虽然Serial垃圾收集器会“Stop The World”但是它是虚拟机运行在Client模式下的默认新生代收集器,它的优点就是单线程,简单高效,** **对于单个CPU环境下它是****效率最高的而且如果所管理的内存不是很大,只是回收几十兆的内存时间还是很短的,用户是可以接受的。** **总之Serial对于运行在Client模式下的虚拟机来说是一个很好的选择。** **二:ParNew收集器(复制算法)** **它是Serial收集器的多线程版本,它们两个之间的区别只有多线程和单线程的区别。它是除类Serial收集外,目前只能与CMS收集器配合工作。** **默认开启的****线程数与CPU的数量相同,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。下面是它和SerialOld收集器的工作图:** **![Center 2][]** **三:Parallel Scavenge收集器(复制算法)** **并行多线程收集器,也被称为吞吐量优先收集器。所谓吞吐量就是CPU用于运行用户代码时间与CPU总消耗时间的比值。** **吞吐量=运行用户代码时间/运行用户代****码时间+垃圾收集时间。Parallel Scavenge收集器提供了两个参数用于精准控制吞吐量,** **分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数(x>0的毫秒数)以及直接设置吞吐量大小的-XX:GCTimeRatio** **参数(设置一个0<x<100的整数,表示垃圾收集器时间占总时间的比率,相当于吞吐量的倒数)。下面是Parallel Scavenge/old收集器工作图:** **![Center 3][]** **四: Serial Old收集器(标记-整理)** **是Serial的老年代版本,同样是单线程收集器,主要是client模式下的虚拟机使用。参考上面图Serial 两大用途:在JDK1.5及之前的版本中与Parallel Scavenge搭配使用;作为CMS收集器的后备预案。在并发收集发生** **Concurrent Mode Failure时使用。** **五: Parallel Old收集器(标记-整理)** **是Parallel Scavenge收集器的老年代版本,使用多线程和标记-整理算法。在JDK1.6中才开始使用。由于之前的版本中,Parallel Scavenge** **只有使用Serial Old****作为老年代收集器,其吞吐量优先的设计思路不能被很好的贯彻,在Parallel Old收集器出现后,这两者的配合主要用** **于贯彻这种思路。和上面的Parallel Scavenge收集器一样的。** **六:CMS收集器(标记-清除)** **CMS收集器是一种以获取最短停顿时间为目标的收集器。它是基于“标记-清除”算法实现的,整个过程分为4个步骤: 初始标记(CMS initial mark):需要用户线程停顿。标记一下GC Roots能直接关联到的对象, 并发标记(CMS concurrent mark):进行GC Roots Tracing的过程。 重新标记(CMS remark):需要用户线程停顿,是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记** **录,这个阶段的****停顿时间一般会比初始标记阶段稍长一些,但比并发标记要短。** **并发清除(CMS concurrent sweep):** **理想的应用场景是B/S架构的服务器。** **工作示意图:** **![Center 4][]** **CMS收集器对CPU资源非常敏感,CMS收集器无法处理浮动垃圾,空间碎片过多(标记-清除算法的弊端),这些就是它的缺点。** **七:G1收集器** **G1收集器与前面的CMS收集器相比有两个显著的改进:一是G1收集器是基于“标记-整理”算法实现的收集器,也就是说它不会产生空间碎片,** **这对于长时间运行的应用系统来说非常重要。二是它可以非常精确地控制停顿,既能让使用者明确指定在一个长度为M毫秒的时间片段内,** **消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。 G1收集器可以实现在基本不牺牲吞吐** **量的前提下完成低停顿的内存回收,这是由于它能够极力地避免全区域的垃圾收集,之前的收集器进行收集的范围都是整个新生代或老年代,** **而G1将整个Java堆(包括新生代、老年代)划分为多个大小固定的独立区域(Region),并且跟踪这些区域里面的垃圾堆积程度,在后台维** **护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域(这就是Garbage First名称的来由)。区域划分及有优先级的区域回收,** **保证了G1收集器在有限的时间内可以获得最高的收集效率。** **工作流程如下:** **![Center 5][]** [Center]: /images/20220713/69fc357feab34060895b4570d0dac076.png [Center 1]: /images/20220713/7ed8eac0f18a4c379bdaa335605f1191.png [Center 2]: /images/20220713/639fdc54629048989d761de53a6a547c.png [Center 3]: /images/20220713/006286620b864cfab203b258f1479405.png [Center 4]: /images/20220713/7117fc6d48b64b96bb5a46bf00f79aa5.png [Center 5]: /images/20220713/85d496e820d44a08ae0a9bccdfb7956d.png
还没有评论,来说两句吧...