在Java的世界里,垃圾回收(Garbage Collection, GC)是一个至关重要的机制,它负责管理程序运行时的内存分配与回收,确保应用程序不会因为内存耗尽而崩溃。本章将深入剖析Java虚拟机(JVM)中的垃圾回收机制,首先聚焦于垃圾回收的基本概念、原理、分类以及JVM中常见的垃圾回收器(上部分),为后续深入理解垃圾回收的策略与优化打下基础。
11.1.1 内存管理与垃圾回收的必要性
Java语言的一大特点是其自动内存管理机制,即程序员无需手动释放不再使用的内存空间,这一任务由JVM的垃圾回收器自动完成。这一特性极大地简化了内存管理的复杂度,降低了内存泄漏和程序崩溃的风险。然而,自动内存管理并不意味着完全没有内存管理的问题,合理的垃圾回收策略和高效的垃圾回收器对程序性能有着重要影响。
11.1.2 垃圾的定义
在JVM中,垃圾通常指的是那些已经失去(或即将失去)任何引用关系的对象所占用的内存空间。这些对象不再被程序中的任何部分所使用,因此它们的内存可以被安全地回收,以便用于新的对象分配。
11.2.1 引用计数法
最简单直观的垃圾回收算法是引用计数法。该方法为每个对象维护一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1。任何时刻计数器为0的对象即可被认定为垃圾。然而,这种方法存在循环引用的问题,即两个对象相互引用,即使它们不再被其他任何对象引用,它们的引用计数器也不会为0,导致内存无法被回收。因此,现代JVM主要采用更为复杂的算法进行垃圾回收。
11.2.2 可达性分析算法
可达性分析算法是现代JVM中主流的垃圾回收算法。它通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,所走过的路径称为引用链(Reference Chain)。当一个对象到GC Roots没有任何引用链相连(即从GC Roots到这个对象不可达)时,则证明此对象是不可用的,即为垃圾对象。GC Roots通常包括虚拟机栈(栈帧中的局部变量表所引用的对象)、方法区中的类静态属性引用的对象、本地方法栈中JNI(即一般说的Native方法)引用的对象等。
根据垃圾回收发生的区域(新生代、老年代),以及回收时是否暂停用户线程的执行,垃圾回收可以分为多种类型。
11.3.1 按回收区域分类
11.3.2 按是否暂停用户线程分类
JVM提供了多种垃圾回收器供用户选择或JVM自动选择,以适应不同的应用场景和性能需求。以下是一些常见的垃圾回收器(上部分):
11.4.1 Serial GC(串行垃圾回收器)
Serial GC是JVM在客户端模式下默认的垃圾回收器,它只使用一个垃圾回收线程进行垃圾回收工作,在垃圾回收时,会暂停所有的用户线程(即STW)。虽然这种回收器简单且容易实现,但由于其单线程的特性,不适合用于服务器环境。
11.4.2 Parallel GC(并行垃圾回收器)
Parallel GC是JVM在服务器模式下默认的垃圾回收器之一(另一个是CMS GC,但在后续版本中逐渐被淘汰)。与Serial GC不同,Parallel GC使用多个线程来执行垃圾回收工作,以提高垃圾回收的效率。Parallel GC支持多核CPU,并且可以通过设置JVM参数来调整垃圾回收的线程数。在垃圾回收时,同样会暂停用户线程的执行,但由于并行执行,其效率通常高于Serial GC。
11.4.3 ParNew GC
ParNew GC是Serial GC的多线程版本,除了使用多线程进行垃圾回收外,其余行为(包括GC Roots的确定、对象的可达性分析等)与Serial GC基本一致。ParNew GC主要用于与CMS GC配合使用,作为CMS GC中新生代的垃圾回收器。
11.4.4 CMS GC(Concurrent Mark Sweep,并发标记清除)
CMS GC是一种以最小停顿时间为目标的垃圾回收器,它旨在减少垃圾回收时的停顿时间,从而提高应用的响应能力。CMS GC主要工作于老年代,分为四个主要阶段:初始标记(Initial Mark)、并发标记(Concurrent Mark)、重新标记(Remark)和并发清除(Concurrent Sweep)。其中,初始标记和重新标记阶段会暂停用户线程的执行,但时间非常短;并发标记和并发清除阶段则与用户线程并发执行。然而,CMS GC存在内存碎片和浮动垃圾(Floating Garbage)等问题,且不适用于堆内存较大的情况。
本章详细介绍了垃圾回收的基本概念、原理、分类以及JVM中几种常见的垃圾回收器(上部分)。通过理解这些内容,读者可以对Java的垃圾回收机制有一个全面的认识。然而,垃圾回收是一个复杂且不断发展的领域,随着JVM技术的不断进步,新的垃圾回收器不断出现,如G1 GC(Garbage-First GC)、ZGC等,它们带来了更高效的垃圾回收策略和更好的性能表现。因此,在后续章节中,我们将继续探讨这些先进的垃圾回收器,以及如何在实际应用中根据具体情况选择合适的垃圾回收器,以达到最优的性能和稳定性。