「译文」Java 垃圾收集参考手册(三):GC 算法基础篇

简介: 「译文」Java 垃圾收集参考手册(三):GC 算法基础篇

相关术语翻译说明:

Mark, 标记;

Sweep, 清除;

Compact, 整理; 也有人翻译为压缩, 译者认为 GC 时不存在压缩这回事。

Copy, 复制; copy 用作名词时一般翻译为拷贝 / 副本, 用作动词时翻译为复制。

注: 《垃圾回收算法手册 》将 Mark and Sweep 翻译为: 标记 - 清扫 算法; 译者认为 标记 - 清除 更容易理解。

GC 算法基础

您应该已经阅读了前面的章节。

本章简要介绍 GC 的基本原理和相关技术, 下一章节 再详细讲解 GC 算法的具体实现。各种垃圾收集器的实现细节虽然并不相同, 但总体而言, 垃圾收集器都专注于两件事情:

  • 查找所有存活对象
  • 抛弃其他的部分, 即死对象, 不再使用的对象。

第一步, 记录 (census) 所有的存活对象, 在垃圾收集中有一个叫做 标记(Marking) 的过程专门干这件事。

标记可达对象(Marking Reachable Objects)

现代 JVM 中所有的 GC 算法, 第一步都是找出所有存活的对象。下面的示意图对此做了最好的诠释:

03_01_Java-GC-mark-and-sweep.png

首先, 有一些特定的对象被指定为 Garbage Collection Roots(GC 根元素)。包括:

  • 当前正在执行的方法里的局部变量和输入参数
  • 活动线程(Active threads)
  • 内存中所有类的静态字段(static field)
  • JNI 引用

其次, GC 遍历 (traverses) 内存中整体的对象关系图(object graph), 从 GC 根元素开始扫描, 到直接引用,以及其他对象(通过对象的属性域)。所有 GC 访问到的对象都被 ** 标记(marked)** 为存活对象。

存活对象在上图中用蓝色表示。标记阶段完成后, 所有存活对象都被标记了。而其他对象 (上图中灰色的数据结构) 就是从 GC 根元素不可达的, 也就是说程序不能再使用这些不可达的对象(unreachable object)。这样的对象被认为是垃圾, GC 会在接下来的阶段中清除他们。

在标记阶段有几个需要注意的点:

在标记阶段, 需要暂停所有应用线程, 以遍历所有对象的引用关系。因为不暂停就没法跟踪一直在变化的引用关系图。这种情景叫做 Stop The World pause (全线停顿), 而可以安全地暂停线程的点叫做安全点(safe point), 然后, JVM 就可以专心执行清理工作。安全点可能有多种因素触发, 当前, GC 是触发安全点最常见的原因。

此阶段暂停的时间, 与堆内存大小, 对象的总数没有直接关系, 而是由 存活对象 (alive objects) 的数量来决定。所以增加堆内存的大小并不会直接影响标记阶段占用的时间。

标记 阶段完成后, GC 进行下一步操作, 删除不可达对象。

删除不可达对象(Removing Unused Objects)

各种 GC 算法在删除不可达对象时略有不同, 但总体可分为三类: 清除 (sweeping)、整理(compacting) 和复制 (copying)。 下一章节 将详细讲解这些算法。

Sweep(清除)

Mark and Sweep(标记 - 清除) 算法的概念非常简单: 直接忽略所有的垃圾。也就是说在标记阶段完成后, 所有不可达对象占用的内存空间, 都被认为是空闲的, 因此可以用来分配新对象。

这种算法需要使用 空闲表(free-list), 来记录所有的空闲区域, 以及每个区域的大小。维护空闲表增加了对象分配时的开销。此外还存在另一个弱点 —— 明明还有很多空闲内存, 却可能没有一个区域的大小能够存放需要分配的对象, 从而导致分配失败(在 Java 中就是 OutOfMemoryError)。

03_02_GC-sweep.png

Compact(整理)

标记 - 清除 - 整理算法 (Mark-Sweep-Compact), 将所有被标记的对象(存活对象), 迁移到内存空间的起始处, 消除了标记 - 清除算法的缺点。 相应的缺点就是 GC 暂停时间会增加, 因为需要将所有对象复制到另一个地方, 然后修改指向这些对象的引用。此算法的优势也很明显, 碎片整理之后, 分配新对象就很简单, 只需要通过指针碰撞(pointer bumping) 即可。使用这种算法, 内存空间剩余的容量一直是清楚的, 不会再导致内存碎片问题。

03_03_GC-mark-sweep-compact.png

Copy(复制)

标记 - 复制算法(Mark and Copy) 和 标记 - 整理算法(Mark and Compact) 十分相似: 两者都会移动所有存活的对象。区别在于, 标记 - 复制算法是将内存移动到另外一个空间: 存活区。标记 - 复制方法的优点在于: 标记和复制可以同时进行。缺点则是需要一个额外的内存区间, 来存放所有的存活对象。

03_04_GC-mark-and-copy-in-Java.png

原文链接: GC Algorithms: Basics

翻译人员: 铁锚 http://blog.csdn.net/renfufei

翻译时间: 2016 年 02 月 06 日

GC 算法概述

学习了 GC 算法的相关概念之后, 我们将介绍在 JVM 中这些算法的具体实现。首先要记住的是, 大多数 JVM 都需要使用两种不同的 GC 算法 —— 一种用来清理年轻代, 另一种用来清理老年代。

我们可以选择 JVM 内置的各种算法。如果不通过参数明确指定垃圾收集算法, 则会使用宿主平台的默认实现。本章会详细介绍各种算法的实现原理。

下面是关于 Java 8 中各种组合的垃圾收集器概要列表, 对于之前的 Java 版本来说, 可用组合会有一些不同:

Young Tenured JVM options
Incremental(增量 GC) Incremental -Xincgc
Serial Serial -XX:+UseSerialGC
Parallel Scavenge Serial -XX:+UseParallelGC -XX:-UseParallelOldGC
Parallel New Serial N/A
Serial Parallel Old N/A
Parallel Scavenge Parallel Old -XX:+UseParallelGC -XX:+UseParallelOldGC
Parallel New Parallel Old N/A
Serial CMS -XX:-UseParNewGC -XX:+UseConcMarkSweepGC
Parallel Scavenge CMS N/A
Parallel New CMS -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
G1 -XX:+UseG1GC

看起来有些复杂, 不用担心。主要使用的是上表中黑体字表示的这四种组合。其余的要么是 被废弃(deprecated), 要么是不支持或者是不太适用于生产环境。所以, 接下来我们只介绍下面这些组合及其工作原理:

  • 年轻代和老年代的串行 GC(Serial GC)
  • 年轻代和老年代的并行 GC(Parallel GC)
  • 年轻代的并行 GC(Parallel New) + 老年代的 CMS(Concurrent Mark and Sweep)
  • G1, 负责回收年轻代和老年代
相关文章
|
1月前
|
算法 安全 Java
Java内存管理:深入理解垃圾收集器
在Java的世界里,内存管理是一块基石,它支撑着应用程序的稳定运行。本文将带你走进Java的垃圾收集器(GC),探索它是如何默默守护着我们的内存安全。我们将从垃圾收集的基本概念出发,逐步深入到不同垃圾收集器的工作机制,并通过实例分析它们在实际应用中的表现。文章不仅旨在提升你对Java内存管理的认识,更希望你能通过这些知识优化你的代码,让程序运行更加高效。
39 3
|
2月前
|
监控 算法 Java
Java内存管理:垃圾收集器的工作原理与调优实践
在Java的世界里,内存管理是一块神秘的领域。它像是一位默默无闻的守护者,确保程序顺畅运行而不被无用对象所困扰。本文将带你一探究竟,了解垃圾收集器如何在后台无声地工作,以及如何通过调优来提升系统性能。让我们一起走进Java内存管理的迷宫,寻找提高应用性能的秘诀。
|
2月前
|
Kubernetes Cloud Native Java
云原生之旅:从容器到微服务的演进之路Java 内存管理:垃圾收集器与性能调优
【8月更文挑战第30天】在数字化时代的浪潮中,企业如何乘风破浪?云原生技术提供了一个强有力的桨。本文将带你从容器技术的基石出发,探索微服务架构的奥秘,最终实现在云端自由翱翔的梦想。我们将一起见证代码如何转化为业务的翅膀,让你的应用在云海中高飞。
|
2月前
|
搜索推荐 算法 Java
手写快排:教你用Java写出高效排序算法!
快速排序(QuickSort)是经典的排序算法之一,基于分治思想,平均时间复杂度为O(n log n),广泛应用于各种场合。在这篇文章中,我们将手写一个Java版本的快速排序,从基础实现到优化策略,并逐步解析代码背后的逻辑。
80 1
|
2月前
|
存储 算法 Java
解释 Java 堆空间和垃圾收集
【8月更文挑战第22天】
28 0
|
14天前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
2月前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
41 2
|
19天前
|
监控 算法 Java
深入理解Java中的垃圾回收机制(GC)
本文将探讨Java的自动内存管理核心——垃圾回收机制。通过详细解析标记-清除算法、复制算法和标记-整理算法等常用垃圾回收算法,以及CMS、G1等常见垃圾回收器,帮助读者更好地理解Java应用的性能优化和内存管理。同时,探讨分代收集、分区收集等策略在实际项目中的应用。结语部分总结了垃圾回收机制在Java开发中的重要性,并展望了未来可能的发展。
19 0
|
2月前
|
安全 算法 Java
java系列之~~网络通信安全 非对称加密算法的介绍说明
这篇文章介绍了非对称加密算法,包括其定义、加密解密过程、数字签名功能,以及与对称加密算法的比较,并解释了非对称加密在网络安全中的应用,特别是在公钥基础设施和信任网络中的重要性。
|
2月前
|
存储 监控 算法
Java的垃圾收集器:理解与应用
【8月更文挑战第21天】在Java的世界里,垃圾收集器(Garbage Collector)是不可或缺的角色,它默默地在后台工作,保证内存的有效利用。本文将探讨Java的垃圾收集机制,包括其工作原理、常见的垃圾收集算法以及如何优化垃圾收集过程。通过了解这些内容,开发者可以编写出更高效、更稳定的Java应用程序。
下一篇
无影云桌面