JVM垃圾回收(笔记)

文章目录

    • 完全垃圾回收
    • 其他垃圾回收类型
    • 垃圾回收器
      • 1. Serial垃圾回收器
      • 2. ParNew垃圾回收器
      • 3. Parallel Scavenge垃圾回收器
      • 4. CMS(Concurrent Mark Sweep)垃圾回收器
      • 5. G1(Garbage First)垃圾回收器
      • 6. ZGC(Z Garbage Collector)和Shenandoah垃圾回收器
    • 垃圾回收算法
      • 1. 标记-清除(Mark-Sweep)算法
      • 2. 复制(Copying)算法
      • 3. 标记-整理(Mark-Compact)算法
      • 4. 分代收集(Generational Collection)算法
      • 5. 增量收集(Incremental Collection)和并发收集(Concurrent Collection)算法

完全垃圾回收

Full GC,即完全垃圾回收,是Java虚拟机(JVM)中的一种垃圾回收机制。它会对整个堆内存进行垃圾回收操作,包括新生代和老年代,有时甚至包括永久代(在Java 8之前)或元空间(在Java 8及以后)。Full GC通常涉及到更多的系统资源,因为它需要暂停应用程序线程来进行垃圾回收,这个过程被称为“Stop-The-World”。

在进行Full GC时,JVM会执行以下步骤:

  1. 标记-清除(Mark-Sweep):首先,JVM会标记出所有可达的(即还在被使用的)对象,然后清除掉所有未被标记的对象。

  2. 压缩(Compact):为了提高内存利用率,JVM可能会将存活的对象移动到内存的一侧,并更新它们的引用地址,这个过程称为压缩。

Full GC的触发条件可能包括:

  • 当老年代的空间不足时,JVM会尝试触发Full GC来释放空间。
  • 当系统调用System.gc()时,虽然这不是推荐的做法,但JVM可能会执行Full GC。
  • 当永久代或元空间不足时,也可能触发Full GC。

Full GC的特点是它会导致应用程序的暂停时间较长,因为在垃圾回收过程中所有的应用线程都需要被暂停。这对于性能敏感的应用程序来说是一个问题,因此通常会尽量避免Full GC的发生,通过优化内存使用、调整垃圾回收器设置或使用其他垃圾回收策略来减少Full GC的影响。

其他垃圾回收类型

除了Full GC(全局垃圾回收)之外,Java中还有其他几种垃圾回收(GC)类型,它们主要用于优化垃圾回收的性能和减少应用程序的停顿时间。以下是一些常见的GC类型:

  1. Minor GC(小型垃圾回收):也称为Young GC,它发生在新生代(Young Generation)空间不足时。新生代包括Eden区和两个Survivor区(S0和S1)。当对象在Eden区创建并且存活一段时间后,会触发Minor GC。在这个过程中,JVM会清理不再使用的对象,并将仍然存活的对象移动到Survivor区。Minor GC通常比较频繁,但是执行速度快。

  2. Major GC(大型垃圾回收):也称为Old GC或Full GC,它发生在老年代(Old Generation)空间不足时。当老年代空间不足以分配新的对象时,会触发Major GC。在这个过程中,JVM会清理老年代中不再使用的对象,并可能涉及将存活的对象从一个区域复制到另一个区域。Major GC通常比较耗时,因为它需要检查整个堆内存。

垃圾回收器

在Java的垃圾回收机制中,有多种垃圾回收器可供选择,每种回收器都有其特定的应用场景和优势。以下是一些常见的Java垃圾回收器:

1. Serial垃圾回收器

  • 特点:Serial垃圾回收器是最基本、历史最悠久的垃圾回收器。它采用单线程模式进行垃圾回收,简单且高效。
  • 适用场景:适用于单核处理器和小内存的应用程序,以及对响应时间没有严格要求的情况。

2. ParNew垃圾回收器

  • 特点:ParNew是Serial的多线程版本,它使用多个线程并行地进行垃圾回收。与Serial相比,ParNew在多核处理器上能够显著提高垃圾回收的效率。
  • 适用场景:适用于多核处理器环境,特别是当应用程序需要快速响应用户请求时。

3. Parallel Scavenge垃圾回收器

  • 特点:Parallel Scavenge以吞吐量最大化为目标,它使用多个线程并行地进行垃圾回收,并通过自适应调节策略来优化性能。此外,它还支持GC日志输出,便于分析和调优。
  • 适用场景:适用于对吞吐量有较高要求的批处理应用程序,如大数据处理等。

4. CMS(Concurrent Mark Sweep)垃圾回收器

  • 特点:CMS垃圾回收器以获取最短回收停顿时间为目标。它采用并发标记清除算法,在垃圾回收过程中尽量减少对应用程序的影响。CMS还支持内存碎片整理功能,以减少内存碎片。
  • 适用场景:适用于对响应时间有严格要求的应用程序,如Web服务器、在线交易系统等。

5. G1(Garbage First)垃圾回收器

  • 特点:G1垃圾回收器是一种面向服务端应用的垃圾回收器,它将堆内存划分为多个独立的区域,并优先回收垃圾最多的区域。G1采用并行和并发的方式进行垃圾回收,以减少停顿时间并提高吞吐量。
  • 适用场景:适用于大内存、多核处理器的应用场景,特别是当应用程序需要同时满足低延迟和高吞吐量的要求时。

6. ZGC(Z Garbage Collector)和Shenandoah垃圾回收器

  • 特点:ZGC和Shenandoah都是新一代的垃圾回收器,它们以极低的停顿时间为目标。ZGC使用读屏障和染色指针等技术来实现并发标记和重定位,而Shenandoah则采用类似的技术但实现方式略有不同。这两种回收器都能够在几乎不影响应用程序性能的情况下完成垃圾回收。
  • 适用场景:适用于对延迟有极高要求的实时应用场景,如金融交易系统、高性能计算等。

需要注意的是,不同的垃圾回收器之间可能存在兼容性问题,因此在选择和使用垃圾回收器时需要仔细考虑应用程序的需求和硬件环境。此外,随着Java版本的更新,新的垃圾回收器和技术也在不断涌现,因此在实际应用中需要保持对新技术的关注和学习。

不同的GC类型适用于不同的应用场景和性能需求。选择合适的垃圾回收器对于优化Java应用程序的性能至关重要。

CMS(Concurrent Mark Sweep)垃圾回收器,也称为并发标记清除垃圾回收器,是Java虚拟机(JVM)中的一种垃圾回收器。它的设计目标是尽量减少应用程序的停顿时间,特别是在响应时间敏感的应用程序中,如Web服务器或实时系统。

CMS GC的工作过程可以分为以下几个阶段:

  1. 初始标记(Initial Mark):这个阶段是在STW(Stop-The-World)模式下进行的,即所有的应用程序线程都会暂停。在这个阶段,垃圾回收器会标记堆中所有存活的对象的根对象。

  2. 并发标记(Concurrent Mark):在初始标记之后,垃圾回收器会与应用程序线程并发执行,标记所有从根对象可达的存活对象。这个阶段不会暂停应用程序线程,因此在应用程序运行的同时进行。

  3. 重新标记(Remark):由于并发标记阶段应用程序线程仍在运行,可能会产生新的存活对象或者有些对象因为应用程序的行为而被错误地标记为垃圾。因此,在并发标记阶段之后,会再次进入STW模式进行重新标记,以确保所有的存活对象都被正确标记。

  4. 并发清除(Concurrent Sweep):在重新标记之后,垃圾回收器会并发地清除所有未被标记的对象,即垃圾对象。这个阶段也不会暂停应用程序线程。

CMS GC的优点是它能够显著减少应用程序的停顿时间,因为它大部分时间都是在与应用程序并发执行的。然而,CMS GC也有一些缺点,比如:

  • 它会产生内存碎片,可能导致老年代空间利用率不高。
  • 在并发标记阶段,如果应用程序线程增长太快,可能会导致更多的浮动垃圾(Floating Garbage)。
  • CMS GC在清理内存时不会压缩堆,这可能导致随着时间推移堆的大小会变得不连续。

由于这些缺点,CMS GC在JDK 9中被标记为废弃,并在后续版本中被G1 GC所取代。

垃圾回收算法

垃圾回收算法是Java等编程语言中用于自动管理内存的一种机制。当对象不再被程序使用时,垃圾回收器会负责回收这些对象占用的内存空间,以便将来再次使用。以下是几种常见的垃圾回收算法:

1. 标记-清除(Mark-Sweep)算法

  • 标记阶段:从一组根对象开始,递归地访问所有可达对象,并将它们标记为活动对象。不可达的对象则不被标记。
  • 清除阶段:遍历堆中的所有对象,将未标记的对象视为垃圾并回收其占用的内存空间。

标记-清除算法的缺点是会产生大量的内存碎片,这可能导致在后续分配大对象时无法找到连续的内存空间。

2. 复制(Copying)算法

  • 将可用内存划分为两个相等的区域,通常称为“From”空间和“To”空间。
  • 每次只使用其中一个区域进行内存分配。当这个区域满时,垃圾回收器会停止程序的执行,将所有活动对象从当前区域复制到另一个区域,然后清空当前区域以释放内存。
  • 交替使用这两个区域,从而实现内存的连续分配和回收。

复制算法的优点是效率高且不会产生内存碎片,但缺点是只利用了一半的内存空间。

3. 标记-整理(Mark-Compact)算法

  • 结合了标记-清除和复制算法的优点。首先进行标记阶段,识别出所有活动对象。
  • 然后,将所有活动对象移动到堆的一端,从而清理出连续的空闲内存空间。这个过程被称为“整理”。
  • 最后,清除边界以外的所有垃圾对象。

标记-整理算法解决了内存碎片的问题,但移动对象的过程可能会带来较大的性能开销。

4. 分代收集(Generational Collection)算法

基于这样一个观察:大多数对象在创建后很快就不再被使用。因此,将堆划分为不同的代(通常是新生代和老年代),并根据对象的年龄进行管理。

  • 新生代:新创建的对象首先被分配到新生代。新生代使用复制算法进行垃圾回收,因为新生代中的对象大多数很快就会变得不可达。
  • 老年代:经过多次垃圾回收仍然存活的对象会被晋升到老年代。老年代使用标记-清除或标记-整理算法进行垃圾回收,因为老年代中的对象相对稳定且占用大量内存。

分代收集算法通过针对不同代的特性采用不同的回收策略,提高了垃圾回收的效率。

5. 增量收集(Incremental Collection)和并发收集(Concurrent Collection)算法

  • 增量收集:为了避免长时间的垃圾回收暂停,增量收集算法将垃圾回收过程分解为多个小步骤,并与程序的执行交替进行。这样可以在不影响程序响应性的情况下完成垃圾回收。
  • 并发收集:并发收集算法在程序运行的同时执行垃圾回收。通过使用多线程或硬件支持,垃圾回收器可以与程序并行地工作,从而减少垃圾回收对程序性能的影响。

这些算法各有优缺点,实际应用中通常会根据具体需求和场景选择合适的算法或组合使用多种算法来实现高效的垃圾回收。

你可能感兴趣的:(Java,jvm,笔记)