ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## **概述** JVM总共有7种垃圾收集器,分别使用不用的回收策略算法用于处理新生代和老年代的数据。 * **新生代收集器**:Serial、ParNew、Parallel Scavenge * **老年代收集器**:CMS、Serial Old、Parallel Old * **整堆收集器**: G1 ## **相关概念** * **并行收集**:指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。 * **并发收集**:指用户线程与垃圾收集线程同时工作(不一定是并行的可能会交替执行)。用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。 * **吞吐量**:即CPU用于运行用户代码的时间与CPU总消耗时间的比值(吞吐量 = 运行用户代码时间 / ( 运行用户代码时间 + 垃圾收集时间 ))。例如:虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99% ## **一. Serial收集器** Serial收集器是最基本的、发展历史最悠久的收集器。 **特点:** 单线程、简单高效(与其他收集器的单线程相比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程手机效率。收集器进行垃圾回收时,必须暂停其他所有的工作线程,直到它结束(Stop The World)。 ## **二. Serial Old收集器** Serial Old是Serial收集器的老年代版本。 ## **三. ParNew收集器** ParNew收集器是Serial收集器的多线程版本。同样用于新生代,采用复制算法。 **特点**:多线程、ParNew收集器默认开启的收集线程数与CPU的数量相同,在CPU非常多的环境中,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。和Serial收集器一样存在Stop The World问题 ## **四. Parallel Scavenge收集器** 吞吐量优先收集器 **特点**: 属于新生代收集器也是采用复制算法的收集器,又是并行的多线程收集器(与ParNew收集器类似)。该收集器的目标是达到一个可控制的吞吐量。可使用GC自适应调节策略(与ParNew收集器最重要的一个区别) **GC自适应调节策略**:Parallel Scavenge收集器可设置-XX:+UseAdptiveSizePolicy参数。当开关打开时不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等,虚拟机会根据系统的运行状况收集性能监控信息,动态设置这些参数以提供最优的停顿时间和最高的吞吐量,这种调节方式称为GC的自适应调节策略。 Parallel Scavenge收集器使用两个参数控制吞吐量: * XX:MaxGCPauseMillis 控制最大的垃圾收集停顿时间 * XX:GCRatio 直接设置吞吐量的大小。 ## **五. Parallel Old 收集器** 是Parallel Scavenge收集器的老年代版本。采用标记-压缩算法。 ## **六. CMS收集器** 一种以获取最短回收停顿时间为目标的收集器。基于标记-清除算法实现。并发收集、低停顿。 **应用场景**:适用于注重服务的响应速度,希望系统停顿时间最短,给用户带来更好的体验等场景下。如web程序、b/s服务。 **CMS收集器的运行过程分为下列4步:** 1. **初始标记**:标记GC Roots能直接关联到的对象。速度很快但是仍存在Stop The World问题。(产生较短停顿) 2. **并发标记**:进行GC Roots Tracing 的过程,并发执行找出存活对象且用户线程。 3. **重新标记**:为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。仍然存在Stop The World问题。(产生较短停顿) 4. **并发清除**:并发执行对标记的对象进行清除回收。 **优缺点:** 由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以响应时间快,但是并发同时会占用CPU资源会降低吞吐量,标记清除算法会导致内存碎片化。 ## **七. G1收集器** 在G1中,堆被划分成 许多个连续的区域(region)。采用G1算法进行回收,吸收了CMS收集器特点。一款面向服务端应用的垃圾收集器。 **特点:** * **并行:** G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短Stop-The-World停顿时间 * **并发:** G1收集器可以通过并发方式和用户线程同时执行,无需暂停用户线程. * **分代算法:** G1能够独自管理整个Java堆,其它收集器需配合使用才行 * **可预测停顿时间:** 可配置在N毫秒内最多只占用M毫秒的时间进行垃圾回收 **G1收集器大致可分为如下步骤:** 1. **初始标记**:仅标记GC Roots能直接到的对象,并且修改TAMS的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象。(产生较短停顿) 2. **并发标记**:从GC Roots开始对堆中对象进行可达性分析,找出存活对象 3. **最终标记**:为了修正在并发标记期间因用户程序执行而导致标记产生变化的那一部分标记记录。(产生较短停顿) 4. **筛选回收**:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。 ## **流行组合** * **Serial**:数据量小的小型应用 * **ParNew + CMS**:对相应速度有要求的中大型应用 * **ParallelYoung + ParallelOld**:对吞吐量有要求的中大型应用 * **G1GC**:可分配较大堆空间的中大型应用