JVM:垃圾回收机制

在这里插入图片描述

概述

垃圾回收机制(Garbage Collection, GC),是 Java 等高级编程语言中的一项自动内存管理技术,用于自动识别和回收不再被程序使用的对象所占用的内存空间,以便后续的内存分配使用。这一机制大大简化了内存管理的工作,减少了内存泄露和程序崩溃的风险,使得开发者可以更加专注于业务逻辑的实现。

垃圾回收算法

JVM 中实现了多种垃圾回收算法,每种算法都有其特点和适用场景。

  1. 分代算法:根据对象生命周期的不同将堆内存划分为不同区域,并对这些区域采取不同的垃圾回收策略。
    工作过程:新建对象首先分配在新生代的 Eden 区中。当 Eden 区填满时会触发 Minor GC 。Minor GC 会扫描 Eden 区和 From Survivor 区,将存活的对象复制到 To Survivor 区(如果 To Survivor 区不足以存放所有存活对象,则部分对象会直接晋升到老年代)。Minor GC 后,Eden 区和 From Survivor 区会被清空,而 To Survivor 区则成为下一次 GC 时的 From Survivor 区。如果对象在 Survivor 区中经过多次 Minor GC 后仍然存活(默认阈值为15次,但可以通过 -XX:MaxTenuringThreshold 参数调整),或者对象太大无法直接在新生代中分配,则会被晋升到老年代中。当老年代空间填满时会触发 Full GC 。Full GC 会扫描整个堆内存(包括新生代和老年代),回收不再使用的对象。
    优点:提高回收效率、减少内存碎片、优化用户体验。

  2. 复制算法:通过复制存活对象到另一个内存区域,并清理原区域的方式来实现垃圾回收。
    工作过程:将堆内存划分为两个大小相等的区域,一个用于当前对象分配( From 区),另一个保持空闲( To 区)。从 GC Roots(根集合)出发,遍历所有可达对象,并将其标记为存活对象。将标记的存活对象从 From 区复制到 To 区。清空 From 区,使其变为空闲状态。将 From 区和 To 区的角色互换,为下一次垃圾回收做准备。
    在这里插入图片描述
    优点:内存分配效率高、避免内存碎片、实现简单。
    缺点:内存利用率低、复制开销大。

  3. 标记清除算法:通过标记和清除两个阶段来回收堆内存中的垃圾对象。
    工作过程:标记阶段 —— 从根对象开始,垃圾回收器遍历对象图,标记所有可以从根对象访问到的存活对象。标记的方式通常是在对象的头信息( Header )中记录为可达对象。清除阶段 —— 在标记完成后,垃圾回收器遍历整个堆内存,清除所有未被标记(即不可达)的对象。这些对象被认为是垃圾,其占用的内存空间将被回收并标记为可用内存,以便后续分配给新的对象。
    优点:处理动态内存分配、实现简单。
    缺点:效率低、内存碎片化、停顿时间较长。

  4. 标记压缩算法:旨在解决标记清除算法中产生的内存碎片问题。
    工作过程:标记阶段(同上)。压缩阶段 —— 在标记完成后,将所有标记为存活的对象移动到堆内存的一端,并按照内存地址依次排序。这样,存活对象之间的空间就被压缩了,而未被标记的对象则被清理掉,其占用的内存空间被释放并标记为可用。
    优点:消除内存碎片、减少内存空间开销。
    缺点:效率较低、需要移动对象、暂停用户应用程序。

  5. 引用计数算法:在对象头中分配一个空间来保存该对象的引用计数。
    工作过程:每个对象维护一个引用计数器,用于记录该对象被引用的次数。每当有一个地方引用该对象时,引用计数器加1;当引用失效时,计数器减1。任何时刻引用计数器为0的对象,即表示该对象不再被任何存活的对象所引用,因此可以判断为垃圾对象,并对其进行回收。
    优点:判定效率高、实现简单。
    缺点:额外空间开销、无法解决循环引用问题。


在 Java 中,对象引用不仅仅是简单的指向堆内存中对象的指针或引用。Java 的垃圾回收机制(GC)为了更有效地管理内存,引入了不同类型的引用,这些引用以不同的方式影响垃圾回收器的行为。

  • 强引用(Strong Reference):最常见的引用类型。如果一个对象具有强引用,那么垃圾回收器绝不会回收,即使内存不足导致抛出 OutOfMemoryError 错误,也不会回收具有强引用的对象。强引用是通过普通的变量赋值来创建的。
  • 软引用(Soft Reference):一种较为柔和的引用方式。如果内存足够,软引用的对象不会被回收;但当 JVM 面临内存不足时,这些对象可能会被垃圾回收器回收。软引用主要用于实现内存敏感的高速缓存。SoftReference 类可以用来创建软引用。
  • 弱引用(Weak Reference):比软引用更弱一些。只要垃圾回收器开始执行,无论当前内存是否足够,都会回收只被弱引用关联的对象。弱引用主要用于在对象被回收时收到一个系统级的通知。WeakReference 类可以用来创建弱引用。
  • 虚引用(Phantom Reference):最弱的一种引用关系。一个对象如果有虚引用,那么其与没有引用几乎是一样的,在任何时候都可能被垃圾回收器回收。虚引用主要用于跟踪对象被垃圾回收器回收的活动。与软引用和弱引用不同,虚引用必须和引用队列( ReferenceQueue )联合使用。当垃圾回收器准备回收一个对象时,如果发现其还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。PhantomReference 类可以用来创建虚引用。

每种引用类型都有其特定的用途,选择合适的引用类型可以帮助开发者更有效地管理内存,避免内存泄漏,并提高程序的性能。

垃圾回收器

垃圾回收器(Garbage Collector,简称GC),是 JVM 中的一个核心组件,负责自动管理堆内存中的对象,通过识别和回收不再被程序使用的对象所占用的内存空间,从而避免内存泄漏并有效使用内存资源。Java 提供了多种垃圾回收器供开发者选择,每种垃圾回收器都有其特定的优点和适用场景。

  • Serial 垃圾回收器:单线程的回收器。收集垃圾时,必须暂停所有应用线程( Stop The World ,简称 STW ),采用复制算法。适合单CPU环境的简单应用。配置参数:-XX:+UseSerialGC ,默认情况下,当可用 CPU 数量少于2时,JVM 会自动选择串行回收器。
  • ParNew 垃圾回收器:Serial 垃圾回收器的多线程版本。新生代并行,采用复制算法;老年代串行,采用标记压缩算法。配置参数:-XX:+UseParNewGC ,JVM 会根据系统配置自行设置。
  • Parallel 垃圾回收器:通过多线程并行的方式加快垃圾回收的速度,适合多 CPU 环境的应用。新生代采用复制算法;老年代采用标记压缩算法。配置参数:-XX:+UseParallelGC -XX:ParallelGCThreads=n ,其中 n 是并行垃圾回收器的线程数,通常设置为与 CPU 核心数相等。
  • CMS( Concurrent Mark Sweep )垃圾回收器:获取最短回收停顿时间为目标的收集器,实现了让垃圾收集线程与用户线程同时工作,减少了垃圾回收时的停顿时间。配置参数:-XX:+UseConcMarkSweepGC ,启用 CMS 垃圾回收器;-XX:+UseCMSCompactAtFullCollection ,用于配置 CMS 垃圾回收器在进行 Full GC 时是否进行内存的压缩整理;-XX:+CMSInitiatingOccupancyFraction=n ,指定了老年代内存占用率达到 n% 时,CMS 垃圾回收器开始执行垃圾回收。
  • G1( Garbage-First )垃圾回收器:面向服务端应用的垃圾回收器,能预测停顿时间并减少停顿时间,同时能处理大内存和大量对象的场景,采用标记压缩算法,但优化了停顿时间的控制。配置参数:-XX:+UseG1GC ,启用 G1 垃圾回收器。

常用的垃圾回收器组合

新生代垃圾回收器老年代垃圾回收器说明
SerialSerial OldSerial 和 Serial Old 都是单线程进行 GC ,GC 时暂停所有应用线程
SerialCMS + Serial OldCMS 是并发 GC ,不需要暂停所有应用线程。另外,当 CMS 进行 GC 失败时,会自动使用 Serial Old 策略进行 GC
ParNewCMSParNew 是 Serial 的并行版本,默认 GC 线程数为 CPU 的数量,也可以指定 GC 线程数
ParNewSerial Old~
ParallelSerial Old~
ParallelParallel OldParallel Old 是 Serial Old 的并行版本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊Q老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值