首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | Java代码是怎么运行的?
02 | Java的基本类型
03 | Java虚拟机是如何加载Java类的?
04 | JVM是如何执行方法调用的?(上)
05 | JVM是如何执行方法调用的?(下)
06 | JVM是如何处理异常的?
07 | JVM是如何实现反射的?
08 | JVM是怎么实现invokedynamic的?(上)
09 | JVM是怎么实现invokedynamic的?(下)
10 | Java对象的内存布局
11 | 垃圾回收(上)
12 | 垃圾回收(下)
13 | Java内存模型
14 | Java虚拟机是怎么实现synchronized的?
15 | Java语法糖与Java编译器
16 | 即时编译(上)
17 | 即时编译(下)
18 | 即时编译器的中间表达形式
19 | Java字节码(基础篇)
20 | 方法内联(上)
21 | 方法内联(下)
22 | HotSpot虚拟机的intrinsic
23 | 逃逸分析
24 | 字段访问相关优化
25 | 循环优化
26 | 向量化
27 | 注解处理器
28 | 基准测试框架JMH(上)
29 | 基准测试框架JMH(下)
30 | Java虚拟机的监控及诊断工具(命令行篇)
31 | Java虚拟机的监控及诊断工具(GUI篇)
32 | JNI的运行机制
33 | Java Agent与字节码注入
34 | Graal:用Java编译Java
35 | Truffle:语言实现框架
36 | SubstrateVM:AOT编译框架
当前位置:
首页>>
技术小册>>
深入拆解 Java 虚拟机
小册名称:深入拆解 Java 虚拟机
### 第十一章 垃圾回收(上) 在Java的世界里,垃圾回收(Garbage Collection, GC)是一个至关重要的机制,它负责管理程序运行时的内存分配与回收,确保应用程序不会因为内存耗尽而崩溃。本章将深入剖析Java虚拟机(JVM)中的垃圾回收机制,首先聚焦于垃圾回收的基本概念、原理、分类以及JVM中常见的垃圾回收器(上部分),为后续深入理解垃圾回收的策略与优化打下基础。 #### 11.1 垃圾回收的基本概念 **11.1.1 内存管理与垃圾回收的必要性** Java语言的一大特点是其自动内存管理机制,即程序员无需手动释放不再使用的内存空间,这一任务由JVM的垃圾回收器自动完成。这一特性极大地简化了内存管理的复杂度,降低了内存泄漏和程序崩溃的风险。然而,自动内存管理并不意味着完全没有内存管理的问题,合理的垃圾回收策略和高效的垃圾回收器对程序性能有着重要影响。 **11.1.2 垃圾的定义** 在JVM中,垃圾通常指的是那些已经失去(或即将失去)任何引用关系的对象所占用的内存空间。这些对象不再被程序中的任何部分所使用,因此它们的内存可以被安全地回收,以便用于新的对象分配。 #### 11.2 垃圾回收的基本原理 **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 垃圾回收的分类 根据垃圾回收发生的区域(新生代、老年代),以及回收时是否暂停用户线程的执行,垃圾回收可以分为多种类型。 **11.3.1 按回收区域分类** - **新生代回收(Minor GC/Young GC)**:主要回收新生代的垃圾,因为新生代中对象生命周期短,存活率低,因此新生代GC频繁但回收速度快。 - **老年代回收(Major GC/Full GC)**:当老年代空间不足时,会触发老年代GC,它可能伴随新生代GC一起进行,也可能是单独进行。老年代GC的回收速度较慢,且会影响应用的性能。 **11.3.2 按是否暂停用户线程分类** - **Stop-The-World(STW)**:在进行垃圾回收时,需要暂停用户线程的执行,直到垃圾回收完成。这是大多数传统垃圾回收器的共同特点。 - **并发(Concurrent)**:垃圾回收与用户线程同时进行,减少STW的时间,提高应用性能。现代JVM中,许多垃圾回收器都支持并发回收。 #### 11.4 JVM中的垃圾回收器(上) 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)等问题,且不适用于堆内存较大的情况。 #### 11.5 总结与展望 本章详细介绍了垃圾回收的基本概念、原理、分类以及JVM中几种常见的垃圾回收器(上部分)。通过理解这些内容,读者可以对Java的垃圾回收机制有一个全面的认识。然而,垃圾回收是一个复杂且不断发展的领域,随着JVM技术的不断进步,新的垃圾回收器不断出现,如G1 GC(Garbage-First GC)、ZGC等,它们带来了更高效的垃圾回收策略和更好的性能表现。因此,在后续章节中,我们将继续探讨这些先进的垃圾回收器,以及如何在实际应用中根据具体情况选择合适的垃圾回收器,以达到最优的性能和稳定性。
上一篇:
10 | Java对象的内存布局
下一篇:
12 | 垃圾回收(下)
该分类下的相关小册推荐:
Java并发编程实战
SpringBoot合辑-初级篇
Java高并发秒杀入门与实战
Java语言基础2-运算符
Java语言基础11-Java中的泛型
Java语言基础10-Java中的集合
Mybatis合辑2-Mybatis映射文件
Java必知必会-Maven初级
手把手带你学习SpringBoot-零基础到实战
SpringBoot零基础到实战
Java语言基础16-JDK8 新特性
Java语言基础13-类的加载和反射