1. GC概述
1.1 什么是GC
GC(Garbage Collection)是Java虚拟机(JVM)中的一项重要功能,用于自动管理堆内存中不再使用的对象,释放其占用的内存空间。GC通过标记和回收无效对象来实现内存的回收和释放,以避免内存泄漏和溢出。
下面是GC的主要工作原理和过程:
1、对象的标记:GC首先标记出所有活动对象,即仍然被引用或可达的对象。它从一组根对象开始,逐步遍历对象图,将可达的对象标记为活动对象,未标记的对象则被认为是无效的。
2、垃圾回收:在标记完成后,GC会对未标记的对象进行回收。具体的回收算法可以是不同的,常见的算法包括标记-复制算法、三色标记算法等。
3、内存压缩和整理:某些垃圾回收算法在回收完对象后,可能会产生内存碎片。为了优化内存使用,GC可能会进行内存压缩和整理操作,使得分配的对象在内存中连续存放,减少内存碎片的影响。
GC的优点是可以自动管理内存,减少了手动内存管理的复杂性,避免了内存泄漏和溢出的问题。但是,GC也会带来一定的性能开销。因此,在开发Java应用程序时,需要合理配置GC的参数和调整垃圾回收策略,以平衡性能和内存的使用。
1.2 Young GC和Full GC
Young GC和Full GC是Java虚拟机(JVM)中的两种垃圾回收(GC)方式,用于回收堆内存中的无效对象。
1、Young GC(Minor GC):Young GC主要针对新生代进行垃圾回收。
- Young GC的目标是尽快回收新生代中的垃圾对象,以便为新对象的分配腾出更多的空间
- 由于新生代中的对象生命周期较短,因此Young GC的频率通常比较高,但每次回收的对象数量相对较少,GC的开销也较小
2、Full GC(Major GC):Full GC是对整个堆内存(包括新生代和老年代)进行垃圾回收的过程。
- Full GC的触发会导致较长时间的停顿,因为它需要扫描和回收整个堆内存,对大量对象进行标记和清除
- Full GC的开销相对较大,相应的STW时间较长,应该尽量避免频繁触发
STW是Stop-The-Word机制的简称,是指在执行垃圾回收过程中,暂停应用程序的执行,即停止所有应用线程的运行。STW是为了确保垃圾回收器能够安全地进行操作,不受应用程序的影响。
1.3 一次完整的GC流程
在JDK 8版本下,一次完整的GC流程大致如下图所示:
一般来说,GC的触发是在对象分配过程中,当一个对象在创建时,他会根据他的大小决定是进入年轻代或者老年代。如果他的大小超过 -xx:PretenureSizeThreshold 就会被认为是大对象,直接进入老年代,否则就会在年轻代进行创建。
在年轻代创建对象时,会先判断Eden区的空间是否充足。如果充足,则直接在Eden区分配内存创建对象;如果不足,则会尝试触发一次Young GC。
在触发Young GC之前,会先进行一次空间分配担保(后续讲解)。如果担保成功,则执行Young GC;如果担保失败了,说明老年代内存空间可能也不足,此时会触发一次Full GC。
2. 垃圾回收中的算法
2.1 判断对象存活的算法
当JVM判新对象不再存活的时候,便会在下一次GC时将该对象回收掉。那么JVM如何判断对象是否存活呢?
JVM有两种算法来判断对象是否存活,分别是引用计数法和可达性分析算法。
- 引用计数法
- 给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1,当引用失效,计数器就减 1
- 任何时候计数器为 0 的对象就是不可能再被使用的
这个方法实现简单,效率高,但是它很难解决对象之间相互循环引用的问题。因此,主流的虚拟机中并没有选择这个算法来管理内存。
2、可达性分析算法: 可达性分析算法基于"GC Roots"的概念,从一组称为GC Roots的根对象开始,通过遍历对象之间的引用链,判断对象是否可以从GC Roots达到。
如果对象可以通过引用链与GC Roots关联,则认为对象是存活的;如果对象无法通过引用链与GC Roots关联,则认为对象不再存活,可以被回收。
2.2 GC Roots
GC Roots是可达性分析算法的起点,想要实现语义正确的可达性分析,就必须完整枚举出所有的GC Roots。
GC Roots可以包括以下几种类型的对象:
-
Class:由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。
-
Thread:活着的线程。
-
Stack Local:栈中的局部变量和方法参数。
-
JNI(Java Native Interface)引用:JNI本地和全局引用。
-
Monitor Used:被同步锁 (synchronized) 持有的对象。
-
Held by JVM:用于JVM特殊目的由GC保留的对象,但实际上这个与JVM的实现是有关的。
- 系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等
2.3 三色标记算法
三色标记算法是一种JVM中垃圾标记的算法,他可以减少JVM在GC过程中的STW时长,他是CMS、G1等垃圾收集器中主要使用的标记算法。
在出现三色标记算法之前,JVM中垃圾对象的标记主要采用可达性分析算法及引用计数法。但是这两种算法存在以下问题:
1、循环引用问题:如果两个对象互相引用,就形成了一个环形结构,如果采用引用计数法的话,那么这两个对象将用于无法被回收。
2、误标记的问题:在多线程环境下,如果一个线程正在遍历对象图,而另一个线程在同时修改对象图,就会导致遍历结果不准确。
3、STW时间长:可达性分析的整个过程都需要STW,以避免对象的状态发生改变,这就导致GC停顿时长很长,大大影响应用的整体性能。
为了解决上面这些问题,引入了三色标记法。
三色标记法将对象分为三种状态:白色、灰色和黑色。
- 白色:该对象没有被标记过
- 灰色:该对象已经被标记过了,但该对象的引用对象还没标记完。
- 黑色:该对象已经被标记过了,并且他的全部引用对象也都标记完了
三色标记法的标记过程可以分为三个阶段:初始标记 (Initial Marking) 、并发标记(Concurrent Marking)和重新标记 (Remark)。
1、初始标记:遍历所有的根对象,将根对象和直接引用的对象标记为灰色。在这个阶段中,垃圾回收器只会扫描被直接或者间接引用的对象,而不会扫描整个堆。因此,初始标记阶段的时间比较短。这个阶段需要STW。
2、并发标记:在这个过程中,垃圾回收器会从灰色对象开始遍历整个对象图,将被引用的对象标记为灰色,并将已经遍历过的对象标记为黑色。并发标记过程中,应用程序线程可能会修改对象图,因此垃圾回收器需要使用写屏障(Write Barrier)技术来保证并发标记的正确性。这个阶段不需要STW。
3、重新标记:重新标记的主要作用是标记在并发标记阶段中被修改的对象以及未被遍历到的对象。这个过程中垃圾回收器会从灰色对象重新开始遍历对象图,将被引用的对象标记为灰色,并将已经遍历过的对象标记为黑色。这个阶段需要STW。
在重新标记阶段结束之后,垃圾回收器会执行清除操作,将未被标记为可达对象的对象进行回收,从而释放内存空间。这个过程中,垃圾回收器会将所有未被标记的对象标记为白色(White)。
以上三个标记阶段中,初始标记和重新标记是需要STW的,而并发标记是不需要STW的。其中最耗时的其实就是并发标记的这个阶段,因为这个阶段需要遍历整个对象树,而三色标记把这个阶段做到了和应用线程并发执行,大大降低了GC的停顿时长。
2.4 垃圾回收算法
JVM中常用的垃圾回收算法包括标记-清除,标记-复制,以及标记-整理。这些算法用于回收不再使用的内存空间,以提高内存利用率和程序性能。
1、标记-清除算法(Mark and Sweep):该算法分为两个阶段。首先,通过可达性分析标记出所有活动对象,然后在清除阶段,清理掉所有未标记的对象,回收它们占用的内存空间。
优点:速度快,因为不需要移动和复制对象。
缺点:会产生内存碎片,造成内存的浪费。
2、标记-复制算法(Mark and Copy):该算法将堆内存划分为两个区域,新创建的对象存放在其中一块儿区域上。在标记阶段,通过可达性分析标记出所有活动对象,并将它们复制到另一个区域。在复制过程中,非活动对象会被忽略(注意:这些对象在在复制的时候其内存空间上是严格排序且连续的)。在复制过程完成后,清理当前区域,这样内存空间就得到了整理,不会产生内存碎片。
优点:内存空间是连续的,不会产生内存碎片。
缺点:
- 浪费了一半的内存空间。
- 复制对象会造成性能和时间上的消耗。
3、标记-整理算法(Mark and Compact):标记-整理算法是结合了上面两者的特点进行演化而来的。该算法将操作分为两个阶段,第一阶段为标记,第二阶段为整理。
- 标记:它的第一个阶段与标记-清除算法是一模一样的,均是遍历 GC Roots,然后将存活的对象标记,清除所有垃圾对象。
- 整理:移动所有存活的对象,且按照内存地址次序依次排列,然后将未端内存地址以后的内存全部回收。因此,第二阶段才称为整理阶段。
优点:
- 不会产生内存碎片
- 不会浪费内存空间
缺点:
- 太耗时间(性能低)
单纯的从时间长短上面来看:标记-清除 < 标记-复制 < 标记-整理。
单纯从结果来看:标记-整理 > 标记-复制 >= 标记-清除。
2.5 新生代和老年代的GC算法
新生代和老年代是Java堆内存的两个主要区域,它们通常使用不同的垃圾回收算法来进行垃圾回收。
1、新生代(Young Generation):新生代是存放新创建的对象的内存区域。由于大部分对象的生命周期较短,新生代使用的垃圾回收算法主要关注对象的快速分配和回收。
新生代通常采用的算法是标记-清除算法,将新生代分为一个Eden区和两个Survivor区。
- 对象首先被分配到Eden区,当Eden区满时,触发垃圾回收,将Eden区中存活对象转移到一块空着的Survivor区(例如S1),Eden区清空。
- 然后再次分配新对象到Eden区,再触发垃圾回收时,将Eden区的存活对象和S1区的存活对象转移到另一块空着的Survivor(例如S2),然后清空Eden区和S1区。
- 当多次 GC 过程完成后,幸存区中的对象存活时间达到了一定阀值(可以用参数 -XX:+MaxTenuringThreshold来指定上限,默认 15),会被看成是"年老"的对象然后直接移动到老年代。
基于这种设计,同时工作的只有一个Eden区和一个Survivor区,另一个Survivor区保持空着的状态用于复制。默认情况下,Eden区域占新生代内存空间的80%,两个Survivor区各占10%,因此内存使用率大约为90%。
通过动态的调整Eden区和Survivor区的比例可以降低空间的浪费。
2、老年代(Old Generation):老年代用于存放生命周期较长的对象,通常使用标记-整理算法进行垃圾回收。在有些回收器上,如CMS,为了降低STW的时长,也会采用标记-清除算法。
2.6 空间分配担保
空间分配担保(Allocation Failure Guarantee)是Java虚拟机中一种用于保证对象分配的机制。它主要应用于新生代的垃圾回收过程中。
在进行新生代的垃圾回收时,通常会采用复制-清除算法,将存活的对象从Eden区复制到Survivor区,并清空Eden区和一个Survivor区。但是,如果Survivor区的空间不足以容纳Eden区和存活对象的总大小,那么一部分对象将通过分配担保机制直接进入老年代。
在每一次执行Young GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间。
如果大于,那么说明本次Young GC是安全的。
如果小于,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小。
- 一共有多少对象在内存回收后存活下来是不可预知的,因此只好取之前每次垃圾回收后晋升到老年代的对象大小的平均值作为参考。
- 如果大于,则尝试进行一次Young GC,但这次Young GC依然是有风险的。
- 如果小于,则会直接触发一次Full GC。
空间分配担保机制的存在是为了避免在进行Minor GC时,频繁地触发Full GC。
但是需要注意的是,担保的结果可能成功,也可能失败。所以,在Young GC的复制阶段执行之后,会发生以下三种情况:
- 剩余的存活对象大小,小于Survivor区,那就直接进入Survivor区
- 剩余的存活对象大小,大于survivor区,小于老年代可用内存,那就直接去老年代
- 剩余的存活对象大小,大于Survivor+老年代,触发"Full GC"
2.7 Young GC和Full GC的触发条件
Young GC的触发条件比较简单,那就是当年轻代中的Eden区分配满的时候就会触发。
Full GC的触发条件比较复杂也比较多,主要以下几种:
1、老年代空间不足
- 创建一个大对象,超过指定阈值会直接保存在老年代当中,如果老年代空间也不足,会触发Full GC。
- Young GC之后,发现要转移到老年代的对象,老年代存不下的时候,会触发一次Full GC。
2、空间分配担保失败
3、永久代空间不足
- 如果有永久代的话,当在永久代分配空间时没有足够空间的时候,会触发Full GC。
4、代码中执行System.gc()
- 代码中执行System.gc0的时候,会触发Full GC,但是并不保证一定会立即触发。
3. 垃圾回收器
3.1 垃圾回收器概述
JVM的垃圾回收器(Garbage Collector)是负责自动回收不再使用的内存空间和释放对象占用的资源的组件,是垃圾回收算法的具体实现。
JVM中的垃圾回收器有多种类型和实现,每种垃圾回收器都有其独特的特点、适用场景和性能表现。常见的垃圾回收器包括:
1、串行垃圾回收器(Serial Garbage Collector):Serial是一款单线程的垃圾回收器,具体包括Serial GC,Serial Old。
2、并行垃圾回收器(Parallel Garbage Collector):Parallel是一款多线程的垃圾回收器,具体包括Parallel Scavenge,Parallel Old,ParNew。
3、并发标记扫描垃圾回收器(CMS Garbage Collector):是一款并发的垃圾回收器,使用标记-清除算法。
4、G1垃圾回收器(G1 Garbage Collector):JDK 7中推出的垃圾回收器,JDK9中设置为默认。
5、ZGC垃圾回收器(The Z Garbage Collector):JDK 11推出。
选择适当的垃圾回收器需要考虑应用程序的性能需求、内存大小、延迟要求以及硬件环境等因素。JVM提供了丰富的垃圾回收器选择,开发者可以根据具体的需求进行配置和调优。
3.2 串行垃圾回收器
串行垃圾回收器(Serial Garbage Collector)是一种单线程垃圾回收器,它是JVM中最古老、最简单的垃圾回收器之一。
1、年轻代回收:采用标记-复制算法,当发生年轻代的垃圾回收时,串行垃圾回收器会暂停所有应用线程(STW),并扫描年轻代中的存活对象。
2、老年代回收:Serial Old是Serial的老年代版本。对于老年代的回收,串行垃圾回收器同样会暂停所有应用线程,然后进行标记-整理算法的垃圾回收。
优点:单线程可以减少上下文切换,减少系统资源的开销。
缺点:在GC的过程中,必须STW。
3.3 并行垃圾回收器
并行垃圾回收器是JVM中的一种垃圾回收器,它通过多线程并行执行垃圾回收操作来提高垃圾回收的吞吐量。在Java HotSpot VM中,存在三种主要的并行垃圾回收器:ParNew、Parallel Scavenge和Parallel Old。
1、ParNew:ParNew其实就是Serial的多线程版本,在参数、回收算法上,和Serial是完全一样的,所以它也是采用标记-复制算法进行垃圾回收。
ParNew在垃圾回收的时候,同样会STW,但是因为它是多线程并行进行垃圾回收的,所以通常情况下时间会比Serial短一些。
2、Parallel Scavenge:Parallel Scavenge是一种主要针对新生代的并行垃圾回收器。它也是基于标记-复制算法,并使用多个线程并行执行垃圾回收操作。Parallel Scavenge的目标是提高应用程序的吞吐量,通过减少垃圾回收时的停顿时间来实现高吞吐量的垃圾回收。
- 吞吐量 = 代码运行时间 / (代码运行时间 + 垃圾收集时间)
3、Parallel Old:Parallel是 Parallel Scavenge的老年代版本,同样是一个关注吞吐量的并行垃圾收集器,他采用的是标记-整理算法进行垃圾回收的。
3.4 CMS
CMS,Concurrent Mark Sweep,同样是老年代的收集器。他也是一个并发执行的垃圾收集器,他和Parallel最大的区别是他更加关注垃圾回收的停顿时间,它采用的是耗时更短的标记-清除算法。
CMS收集器的工作流程主要有下面4个步骤
1、初始标记:独占CPU,仅标记GC Roots能直接关联的对象。(STW)
2、并发标记:可以和用户线程并发执行,标记所有可达对象。
3、重新标记:独占CPU,对并发标记阶段用户线程运行产生的垃圾对象中产生变动的一部分对象进行标记修正。(STW)
4、并发清理:可以和用户线程并发执行,清理垃圾。
从上面的四个步骤中可以看出,CMS的过程中,只有初始标记和重新标记这两个步骤是STW的,所以相比其他的收集器整个回收过程都STW来说,他导致的应用停顿时间更短。
CMS的缺点:
1、对CPU非常敏感:在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分线程使应用程序变慢。
2、无法处理浮动垃圾:在最后一步并发清理过程中,用户线程执行也会产生垃圾,但是这部分垃圾是在标记之后,所以只有等到下一次GC的时候清理掉,这部分垃圾叫浮动垃圾。
3、CMS使用"标记-清理"法会产生大量的空间碎片。
- 当碎片过多,往往会出现老年代还有很大的空间但无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。
- 为了解决这个问题,CMS提供了一个开关参数,用于在碎片过多要触发Full GC时开启内存碎片的合并整理过程。
- 但是内存整理的过程是无法并发的,虽然可以清理内存碎片,但是停顿时间变长了。
3.5 G1
G1,Garbage First,是CMS的改进版,解决了CMS内存碎片、更多的内存空间等问题。在JDK 9之后,G1成为了默认的垃圾回收器。
在G1中,堆不再分成连续的年轻代和老年代空间,而是划分为多个(通常是2048个)可以存放对象的小堆区(smaller heap regions)。每个小堆区都可能是Eden区, Survivor区或者Old区。在逻辑上, 所有的Eden区和Survivor区合起来就是年轻代,所有的Old区拼在一起那就是老年代,如下图所示:
这样的划分使得GC不必每次都去收集整个堆空间,而是以增量的方式来处理。GC时每次只处理一部分小堆区,称为此次的回收集(collection set)。GC事件的每次暂停都会收集所有年轻代的小堆区,同时也可能包含一部分老年代小堆区,如下图所示:
G1以一种和CMS 相似的方式执行垃圾回收。G1在并发标记阶段估算每个小堆区存活对象的总数,垃圾最多的小堆区会被优先收集,这也是G1名称的由来。
G1基于标记,清理对应的regions时,会将对象从一个或多个region里复制到另一个region里,在这个过程中会伴随着压缩和释放内存。清理过程在多核机器上采用并行执行,来降低停顿时间,增加吞吐量。
G1会基于以往的收集数据,来评估用户指定的停顿时间可以回收多少regions,需要花费的时间,然后确定停顿时间内可以回收多少个regions。
G1的优势如下:
1、并发回收:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU (CPU或者CPU核心) 来缩短STW的停顿时间。
- 一些在其他垃圾收集器需要停顿Java线程来执行的GC动作,在G1收集器中可以通过并发的方式实现
2、分代收集:分代概念在G1中依然存在。虽然G1可以不需要其它收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新生代和老年代的对象,以获取更好的收集效果。
3、空间整合:由于G1使用了独立区域(Region)概念,G1从整体来看是基于标记-整理 算法实现收集,从局部(两个Region)上来看是基于标记-复制算法实现的。但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片。
4、可预测的停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
5、支持热插拔:G1可以在运行时动态调整堆的大小,以适应不同的内存需求。
G1是一种面向大型内存环境的垃圾回收算法,适合在以下场景中使用:
1、大型内存环境:G1针对大型内存环境进行了优化,因此对于使用了大量内存的应用程序来说(超过4G),G1是一个更好的选择。
2、对应用程序响应时间敏感的场景:G1通过分配多线程来进行垃圾回收,以最大限度地减少回收时应用程序的暂停时间。
3、对内存使用效率敏感的场景: G1可以更好地评估哪些内存空间可以释放,以此来提高内存的利用率。
4、动态内存需求的场景:G1支持热插拔,可以在运行时动态调整堆的大小,以适应不同的内存需求
5、要求回收时间具有可预测性的场景:G1使用固定的内存分配块来管理堆内存,这使得其在回收时间上具有更高的可预测性。
3.6 ZGC
ZGC是Java 11中引入的一种新的垃圾回收器。它的设计目标是实现几乎无感知的垃圾回收停顿,即在执行垃圾回收时,最大程度地减少应用程序的停顿时间。
ZGC的主要特点包括:
1、低停顿时间:ZGC致力于最小化垃圾回收引起的停顿时间。它通过并发执行垃圾回收操作,减少了垃圾回收期间的停顿时间。通常,ZGC的停顿时间在几毫秒到几十毫秒之间,并且随着堆大小的增加而保持稳定。
2、分代无关:与传统的分代垃圾回收器不同,ZGC没有明确定义的分代概念。它的设计理念是在整个堆上执行垃圾回收,而不仅仅是特定的年轻代或老年代。这种分代无关的设计可以减少垃圾回收器的复杂性,提高整体性能。
3、并发整理:ZGC使用了并发标记算法来标记存活对象。标记过程与应用程序的执行并发进行,几乎没有停顿时间。然后,它使用一种称为"Relocation"的技术来并发地移动和整理对象,以提供更大的连续可用内存空间。
4、可伸缩性:ZGC的设计注重可伸缩性,可以适应各种不同的应用程序需求和堆大小。它可以根据应用程序的需要自动调整垃圾回收的线程数量,并且可以动态地调整停顿时间目标。
ZGC适用于需要低停顿时间和大堆内存的应用程序,特别是那些对实时性要求较高的场景。
但需要注意的是,ZGC在某些特定情况下可能会牺牲一些吞吐量,因此在选择垃圾回收器时应根据应用程序的需求进行权衡。
3.7 老年代和新生代中的垃圾回收器
新生代垃圾回收器有Serial、ParNew、Parallel Scavenge。
老年代垃圾回收器有Serial Old、Parallel Old、CMS。
整堆垃圾回收器有G1、ZGC。
3.8 JVM参数-设置垃圾回收器
Java8版本的Hotspot JVM,默认情况下使用的是并行垃圾收集器(Parallel GC)。Java9之后,官方JDK默认使用的垃圾收集器是G1。可以通过JVM的参数来指定使用哪个垃圾回收器。
1、-XX:+UseSerialGC:使用串行垃圾回收器。
2、-XX:+UseParallelGC:使用并行垃圾回收器。
3、-XX:+UseParallelOldGC:使用并行老年代垃圾回收器
4、-XX:+UseConcMarkSweepGC:使用并发标记-清除(CMS)垃圾回收器。
5、-XX:+UseG1GC: 使用G1(Garbage First)垃圾回收器。
4. 总结
1、GC(Garbage Collection)是Java虚拟机(JVM)中的一项重要功能,用于自动管理堆内存中不再使用的对象,释放其占用的内存空间
2、Young GC和Full GC是Java虚拟机(JVM)中的两种垃圾回收(GC)方式,用于回收堆内存中的无效对象
3、JVM有两种算法来判断对象是否存活,分别是引用计数法和可达性分析算法
4、GC Roots是可达性分析算法的起点,想要实现语义正确的可达性分析,就必须完整枚举出所有的GC Roots
5、三色标记算法是一种JVM中垃圾标记的算法,他可以减少JVM在GC过程中的STW时长,他是CMS、G1等垃圾收集器中主要使用的标记算法
6、JVM中常用的垃圾回收算法包括标记-清除(Mark and Sweep),标记-复制(Mark and Copy),以及标记-整理(Mark and Compact)
7、空间分配担保(Allocation Failure Guarantee)是Java虚拟机中一种用于保证对象分配的机制,它主要应用于新生代的垃圾回收过程中
8、JVM的垃圾回收器(Garbage Collector)是负责自动回收不再使用的内存空间和释放对象占用的资源的组件,是垃圾回收算法的具体实现
9、JVM中的垃圾回收器有多种类型和实现,每种垃圾回收器都有其独特的特点、适用场景和性能表现
- 串行垃圾回收器(Serial Garbage Collector):Serial是一款单线程的垃圾回收器,具体包括Serial GC,Serial Old
- 并行垃圾回收器(Parallel Garbage Collector):Parallel是一款多线程的垃圾回收器,具体包括Parallel Scavenge,Parallel Old,ParNew
- 并发标记扫描垃圾回收器(CMS Garbage Collector):是一款并发的垃圾回收器,使用标记-清除算法
- G1垃圾回收器(G1 Garbage Collector):JDK 7中推出的垃圾回收器,JDK9中设置为默认
- ZGC垃圾回收器(The Z Garbage Collector):JDK 11推出