JVM——垃圾收集算法及垃圾回收器

本文详细介绍Java中的垃圾回收算法,包括标记—清除算法、复制算法、标记整理算法及分代回收算法,并介绍了各种垃圾回收器的特点及适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、垃圾回收算法

1、标记—清除算法

1)工作流程

算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象(标记阶段),在标记完成后统一回收所有被标记的对象(回收阶段)。

2)缺点

a. 效率问题:标记和清除这两个过程的效率都不高。

b. 空间问题:会产生大量的不连续碎片。


2、复制算法(新生代垃圾回收算法)

1)工作流程

    将内存划分为大小相等的两块,每块只使用其中的一块,另外一块作为保留区域,当进行垃圾回收时,将使用区域的存活对象一次性进行赋值到保留区域,而后一次性清空使用区域。

2)使用场景

     新生代垃圾回收,新生代对象具有朝生夕灭的特性(新生代对象存活率低)。

3)优点:实现简单,运行效率高,无空间碎片问题。

4)JVM采用的复制算法:

   将内存划分(新生代内存)为一块较大的Eden区域和两块大小相等、空间较小的Survivor区域(EdenSurvivor = 8:1)。

   每次使用Eden和其中的一块Survivor区域(第一块Survivor区域为from区域,另外一块为to区域)。

   在进行垃圾回收时(Eden区域快满时,系统自动触发垃圾回收)

A. 第一次进行GC时,将Eden区中的对象移动到from区域。

B. 第二次再进行GC时,将Eden区和from区中存活的对象移动到to区域,然后一次性清除掉Edenfrom区,以此循环。

C. 对象在from区域和to区域来回移动15次(默认),将对象移动到老年代。

D. 特殊情况:当Survivor区域放不下存活对象时,会从老年代进行分配担保。


3、标记整理算法(老年代回收算法)

复制算法在对象存活率比较高的情况下,会有大量对象复制操作,效率很低,因此,老年代不采用复制算法。

1)工作流程:

       标记阶段和标记清除阶段的标记类似,标记出无用对象。

       整理阶段:将存活对象向一端移动,而后一次性将存活对象边界以外的空间清除掉。

 

4、分代回收算法

   Java采用分代回收算法,即新生代采用复制算法,而老年代采用标记整理算法。

   将内存划分为新生代(对象存活率低)和老年代(对象存活率高)。


面试考点:请问了解Minor GCMajor GC吗?

Minor GC:新生代GC,指的是新生代垃圾回收,在新生代中,对象大多数朝生夕灭,因此采用复制算法,Major GC发生频繁,效率较高,

Major GC (老年代GC/Full GC):指的是发生在老年代的垃圾回收,发生Full GC通常会至少发生一次Minor GC,但并非绝对,Full GC 速度比Minor G从速度慢10倍以上,发生频率较低。

 

二、垃圾回收器

并行:指的是多条垃圾回收线程并行工作,而用户线程等待。

并发:用户线程与垃圾回收线程同时执行(不一定并行,可能交替执行),用户线程继续执行,垃圾回收线程运行在另外的内核中。

吞吐量:CPU运行用户代码时间/CPU总时间

        CPU总时间即用户代码时间+垃圾回收时间

新生代垃圾回收器:SerialParNewParallel scavenge

老年代垃圾回收器:SeralOldParallelOldCMS

全区域垃圾回收器:G1

1、Serial收集器(新生代垃圾回收,串行收集器)

(1)特性:Serial是一个单线程收集器,在Serial进行垃圾收集时,必须暂停其他所有的工作线程,直到Serial收集器手机结束(STW)。

(2)应用场景:Serial收集器是JVM运行在Client模式下默认的新生代收集器。

(3)优点:简单而高效,对于单核CPUSerial收集器由于没有线程交互开销,可以获得最高的单线程收集效率。

2、ParNew收集器(新生代收集器,并行GC

(1)特性:ParNew收集器是Serial收集器的多线程版本。

(2)应用场景:PerNew是许多运行在Serial模式下的JVM首选新生代收集器。

(3)优点:随着可使用CPU数量的增加,对于GC时系统资源的利用有较大帮助。

3、Parallel Scavenge 收集器(吞吐量有限收集器,新生代收集器,并行GC

(1)特性:吞吐量

   两个参数控制吞吐量:

   a. .-xx:MaxGCPauseMillis:控制最大垃圾收集器停顿时间。

   b. .-xx:GCRatio:直接设置吞吐量大小

(2)应用场景:高吞吐量场景,适合需要与用户交互的程序(B/S架构),良好的响应速度提升用户体验。

(3)优点:与ParNew收集器比较:高吞吐量。

      GC自调节策略(-xx+UseAdaptiveSizePolicy

4、Serial Old收集器(老年代收集器,并行GC

(1)特性:Serial OldSerial老年代版本,单线程收集器,实用标记整理算法。

(2)应用场景:

     1)Client模式下:Serial Old主要也在于给Client模式下的虚拟机使用。

     2)Server模式下:作为CMS收集器的后备预案,当CMS发生并发失败问题时使用。

5、Parallel Old收集器(老年代收集器,并行GC

(1)特性:Parallel OldParallel Scavenge老年代版本。

(2)应用场景:注重吞吐量以及CPU资源敏感场合。

6、CMS(老年代垃圾收集器,并行GC):采用标记清除算法

(1)特性:CMS收集器是以获得最短系统停顿时间为目标的垃圾回收器。

(2)应用场景:B/S系统:服务端。B/S系统重视服务器的响应速度,希望系统停顿时间尽可能短,CMS收集器非常符合此类应用需求。

(3)优点:并发收集,低停顿。

(4)缺点:对CPU资源敏感,产生大量空间碎片。

7、G1(全区域垃圾回收器)

应用场景:应用于低停顿场景。


### JVM 常用的垃圾回收算法及其工作原理 #### 标记-清除算法 (Mark-Sweep) 标记-清除算法是最基本的一种垃圾收集方法。该算法分为两个主要阶段: - **标记阶段**:遍历对象图并标记所有可访问的对象,确保这些对象不会被误删。 - **清除阶段**:扫描堆内存中的对象,释放那些未被标记(即不可达)的对象所占有的空间。 这种方法简单直观,但在实际应用中有两大缺陷:效率低以及容易产生大量碎片化内存[^5]。 #### 复制算法 (Copying) 为了克服标记-清除法产生的内存碎片问题,引入了复制算法。此算法将可用内存按容量划分为大小相等的两部分,每次只使用其中一部分,在进行垃圾回收时把存活对象复制到另一部分区域中去。这样不仅解决了内存碎片的问题,而且由于只需要移动指针即可完成清理操作,因此速度更快。不过这种做法浪费了一半的空间资源[^2]。 ```java // 示例代码展示如何模拟简单的复制过程 public class CopyingGC { private static final int MAX_HEAP_SIZE = 8 * 1024; // 单位KB public void copyObjects() { Object[] fromSpace = new Object[MAX_HEAP_SIZE / 2]; Object[] toSpace = new Object[MAX_HEAP_SIZE / 2]; // 执行复制逻辑... } } ``` #### 标记-整理算法 (Mark-Compact) 标记-整理算法综合了前两种方案的优点。同样先经过一轮完整的标记过程来识别哪些对象仍然活跃;之后不是直接删除无用对象腾出位置给新创建的数据结构,而是让所有的存活对象向一端聚集靠拢,从而消除因多次分配释放造成的零散空闲区。这种方式既避免了内存碎片又提高了存储利用率[^4]。 #### 分代收集算法 (Generational Collection) 考虑到大多数情况下新生代中的对象生命周期较短而老年代里的则相对持久的特点,分代收集算法应运而生。整个堆被分割成几个不同年龄层次的部分——年轻代(Young Generation) 年老代(Tenured/Old Generation),针对各自特性采取最适宜它们自身的回收方式。比如对于年轻人来说采用快速但可能不彻底的方式处理,而对于老年人则更倾向于稳健可靠的策略[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值