1. Overview
1.概述
Java 21 debuted in September 2023, along with the introduction of the Generational ZGC. Building on the efficiency of the Z Garbage Collector, this update focuses on optimizing memory management by introducing separate generations for young and old objects.
Java 21 于 2023 年 9 月首次发布,同时引入了代 ZGC。该更新以 Z 垃圾收集器的效率为基础,重点优化内存管理,为新旧对象分别引入不同的世代。
In this article, we’ll closely examine this addition, exploring its potential benefits, how it works, and how to use it.
在本文中,我们将仔细研究这一新增功能,探讨它的潜在优势、工作原理和使用方法。
2. Garbage Collection
2.垃圾收集
To begin our exploration, let’s delve into the realm of memory management. Garbage collection is the process by which programs try to free up allocated memory that is no longer used by objects. An object is considered ‘in-use’ or ‘referenced’ if some part of our program still maintains a pointer to it. Conversely, an ‘unused’ or ‘unreferenced’ object is no longer accessed by any part of our program, allowing the memory it occupies to be reclaimed.
作为探索的开始,让我们深入了解一下内存管理。垃圾回收是程序尝试释放已分配的、不再被对象使用的内存的过程。如果我们程序的某些部分仍在维护指向对象的指针,那么该对象就被视为 “使用中 “或 “引用 “对象。相反,”未使用 “或 “未引用 “对象不再被程序的任何部分访问,因此其占用的内存可以被回收。
For example, in Java, the garbage collectors are responsible for freeing up the heap memory, which is where Java objects are stored.
例如,在 Java 中,垃圾回收器负责释放堆内存,它是 Java 对象的存储空间。
This helps prevent memory leaks and ensures efficient resource usage. It also frees us from having to manually manage the program’s memory, which can lead to potential bugs. Some programming languages, such as Java or C#, come with this feature built-in, while others, like C or C++, may rely on external libraries for similar functionality.
这有助于防止内存泄漏并确保资源的有效使用。它还使我们不必手动管理程序的内存,而这可能会导致潜在的错误。一些编程语言(如 Java 或 C#)内置了这一功能,而其他编程语言(如 C 或 C++)则可能依赖外部库来实现类似功能。
3. Generational Garbage Collection
3.代垃圾收集
In the context of memory management, a generation refers to a categorization of objects based on the time of their allocation.
在内存管理中,代指的是根据分配时间对对象进行分类。
Let’s shift our focus to generational garbage collection. This represents a memory management strategy and works by dividing the objects into different generations, based on the time of allocation, and applying different approaches based on their generation.
让我们把注意力转移到代际垃圾回收上。这是一种内存管理策略,其工作原理是根据分配时间将对象分为不同的世代,并根据其世代应用不同的方法。
In the context of Java, the memory is partitioned into two main generations: young and old. Newly created objects find their place in the young generation, where frequent garbage collection takes place. Objects that persist beyond multiple garbage collection cycles are promoted to the older generation. This division optimizes efficiency by acknowledging the short lifespan of most of the objects.
在 Java 中,内存主要分为两代:年轻的一代和年老的一代。新创建的对象在年轻代中找到自己的位置,在年轻代中经常进行垃圾回收。持续存在多个垃圾回收周期的对象会被提升到老一代。这种划分承认大多数对象的生命周期较短,从而优化了效率。
For more information regarding the generational garbage collection in Java, see the article Java Garbage Collection Basics.
有关 Java 中代际垃圾回收的更多信息,请参阅文章 Java 垃圾回收基础。
4. The Z Garbage Collector
4.Z 垃圾回收器
The Z Garbage Collector, also known as ZGC, is a scalable, low-latency garbage collector. It was first introduced in Java 11 as an experimental feature and became production-ready in Java 15.
Z 垃圾收集器(又称 ZGC)是一种可扩展、低延迟的垃圾收集器。它在 Java 11 中首次作为实验功能引入,并在 Java 15 中投入生产。
The purpose of this feature was to minimize or eliminate long garbage collection pauses, thereby enhancing application responsiveness and accommodating the growing memory capacities of modern systems.
该功能的目的是尽量减少或消除长时间的垃圾回收停顿,从而提高应用程序的响应速度,并适应现代系统不断增长的内存容量。
As a non-generational approach, it stores all objects together, regardless of age, so each cycle collects all objects.
作为一种非代际方法,它将所有对象存储在一起,不分年龄,因此每个周期都会收集所有对象。
5. The Generational Z Garbage Collector
5.Z 世代垃圾收集器
The Generational ZGC aims to improve application performance, extending the existing ZGC by maintaining separate generations for young and old objects.
分代 ZGC 旨在提高应用程序性能,通过为新旧对象保留 不同的代来扩展现有的 ZGC。
5.1. Motivation
5.1.动机
For most use cases, ZGC is enough to solve latency problems related to garbage collection. This works well as long as there are enough resources available to ensure that the garbage collector can reclaim memory faster than our program consumes it.
对于大多数使用案例,ZGC 足以 解决与垃圾回收相关的延迟问题。 只要有足够的可用资源来确保垃圾回收器回收内存的速度快于我们的程序消耗内存的速度,这种方法就能很好地发挥作用。
However, the weak generational hypothesis states that most objects die young. Consequently, collecting and reclaiming memory from these short-lived young resources requires fewer computational resources. This process unlocks more memory quickly.
然而,弱世代假说指出,大多数对象都会在年轻时死亡。因此,从这些寿命较短的年轻资源中收集和回收内存所需的计算资源较少。这一过程可以快速释放更多内存。
On the other hand, collecting older objects, which have survived multiple cycles and have a more extended lifespan, demands more computational resources. However, the amount of memory unlocked by collecting older objects is comparatively less. This strategy proves more efficient in quickly freeing up memory, contributing to enhanced overall application performance.
另一方面,收集经过多次循环且寿命更长的旧对象需要更多的计算资源。不过,通过收集旧对象解锁的内存量相对较少。事实证明,这种策略在快速释放内存方面更为高效,从而有助于提高应用程序的整体性能。
更多信息
5.2. Goals
5.2.目标
The Generational ZGC aims to deliver some key advantages compared to the non-generational ZGC:
与非代际ZGC相比,代际ZGC旨在提供一些关键优势:
- reduced risks of allocation stalls
- decreased heap memory overhead requirements
- lowered garbage collection CPU overhead
Additionally, the goal is to add these advantages while preserving already existing benefits of using the non-generational approach:
此外,我们的目标是在增加这些优势的同时,保留使用非世代方法的现有优势:
- pause times lower than one millisecond
- support for heap sizes up to many terabytes
- minimal manual configuration
To maintain the last point, the new GC doesn’t need any manual configuration for the size of the generations, the number of threads used, or how long objects should reside in the young generation.
为了保持最后一点,新的 GC 无需手动配置代的大小、使用的线程数或对象在年轻代中的驻留时间。
5.3. Description
5.3.说明
The Generational ZGC introduces a two-generation heap structure: the young generation for recent objects and the old generation for long-lived ones. Each generation is independently collected, prioritizing the frequent collection of young objects.
代际 ZGC 引入了一种两代堆结构:年轻一代堆放最近的对象,老一代堆放寿命长的对象。每一代都独立收集,优先频繁收集年轻对象。
Concurrent collection, similar to non-generational ZGC, relies on colored pointers, load barriers, and store barriers for consistent object graph views. Colored pointers contain metadata, facilitating efficient 64-bit object pointer usage. Load barriers interpret metadata, while store barriers handle metadata addition, maintain remembered sets, and mark objects as alive.
并发收集与非代 ZGC 类似,依靠彩色指针、加载障碍和存储障碍来实现一致的对象图视图。彩色指针包含元数据,有助于高效使用 64 位对象指针。加载障碍会解释元数据,而存储障碍会处理元数据添加、维护记忆集,并将对象标记为存活对象。
5.4. Enabling Generational ZGC
5.4.促进世代相传的 ZGC
For a smooth transition, the Generational ZGC will be available alongside the non-generational ZGC. The -XX:UseZGC command-line option will select the non-generational ZGC. To select the Generational ZGC, we need to add the -XX:+ZGenerational option:
为了平稳过渡,世代 ZGC 将与非世代 ZGC 同时使用。-XX:UseZGC命令行选项将选择非世代 ZGC。要选择世代 ZGC,我们需要添加 -XX:+ZGenerational 选项:
java -XX:+UseZGC -XX:+ZGenerational ...
The Generational ZGC is intended to become the default one in a future Java release. Moreover, in an even later release, the non-generational ZGC may be removed entirely.
在未来的 Java 版本中,代 ZGC 将成为默认 ZGC。此外,在更晚的版本中,非世代 ZGC 可能会被完全删除。
5.5. Risks
5.5.风险
The integration of barriers and colored pointers in the new GC introduces higher complexity, surpassing its non-generational counterpart. The Generational ZGC also runs two garbage collectors concurrently. These collectors are not totally independent, as they interact in some cases, adding complexity to the implementation.
新的 GC 集成了障碍和彩色指针,从而带来了更高的复杂性,超过了非世代性的同类产品。世代 ZGC 还同时运行两个垃圾收集器。这些收集器并非完全独立,它们在某些情况下会相互作用,从而增加了实现的复杂性。
Although it is expected to excel in most use cases, certain workloads pose a risk of slight performance degradation. To address this issue, continuous evolution and optimization of the Generational ZGC will be driven by benchmarks and user feedback, aiming to address and mitigate these identified risks over time.
虽然它有望在大多数使用案例中表现出色,但某些工作负载会带来轻微的性能下降风险。为解决这一问题,一代 ZGC 将根据基准和用户反馈不断演进和优化,以逐步解决和降低这些已发现的风险。
6. Generational ZGC Design Differences
6.ZGC 设计的代际差异
The Generational ZGC introduces several design differences, enhancing garbage collection efficiency and user adaptability compared to its non-generational counterpart.
与非一代 ZGC 相比,一代 ZGC 引入了若干设计差异,提高了垃圾收集效率和用户适应性。
6.1. Enhanced Performance with Optimized Barriers
6.1.通过优化屏障提高性能
Generational ZGC discards multi-mapped memory in favor of explicit code within load and store barriers. To accommodate store barriers and revised load barrier responsibilities, Generational ZGC employs a highly optimized barrier code. Leveraging techniques such as fast paths and slow paths, the optimized barriers ensure maximum throughput and performance for applications, even under intensive workloads.
新一代 ZGC 摒弃了多映射内存,转而在加载和存储障碍中使用显式代码。为了适应存储障碍和修改后的加载障碍职责,一代 ZGC 采用了高度优化的障碍代码。利用快速路径和慢速路径等技术,优化后的障碍即使在高强度工作负载下也能确保应用程序获得最大的吞吐量和性能。
6.2. Efficient Inter-Generational Pointers Tracking
6.2.高效的代际指针跟踪
Double-buffered remembered sets — organized in pairs for each old-generation region — use bitmaps for efficient tracking of inter-generational pointers. This design choice facilitates concurrent work by application and garbage collection threads without the need for extra memory barriers, resulting in smoother execution.
双缓冲记忆集–每个旧一代区域成对组织–使用位图来有效跟踪跨代指针。这种设计选择方便了应用程序和垃圾回收线程的并发工作,而无需额外的内存障碍,从而实现了更流畅的执行。
6.3. Optimized Young Generation Collection
6.3.优化的年轻一代收集
By analyzing the density of young generation regions, Generational ZGC selectively evacuates regions, reducing the effort required for young generation collection. This optimization contributes to quicker and more efficient garbage collection cycles for improved application responsiveness.
通过分析年轻一代区域的密度,Generational ZGC 可以有选择性地疏散区域,从而减少年轻一代收集所需的工作量。这种优化有助于更快、更高效地完成垃圾回收周期,从而提高应用程序的响应速度。
6.4. Flexible Handling of Large Objects
6.4.灵活处理大型物体
Generational ZGC introduces flexibility in handling large objects by allowing them to be allocated to the young generation. This eliminates the need for preemptive allocation to the old generation, enhancing memory efficiency. Large objects can now be collected in the young generation if short-lived or efficiently promoted to the old generation if long-lived.
代 ZGC 允许将大型对象分配给年轻一代,从而引入了处理大型对象的灵活性。这样就不需要抢先分配到老一代,从而提高了内存效率。现在,如果大型对象的寿命较短,则可将其收集到年轻一代中;如果大型对象的寿命较长,则可将其高效地提升到老一代中。
7. Conclusion
7.结论
As we’ve learned throughout this article, Java 21 comes with a powerful feature, the Generational ZGC. With careful consideration of potential risks and a commitment to ongoing refinement based on user feedback, it is expected to offer enhanced efficiency and responsiveness, making it a valuable addition to Java’s evolving ecosystem.
正如我们在本文中所了解到的,Java 21 具有一个强大的功能,即世代 ZGC。在仔细考虑潜在风险并致力于根据用户反馈不断改进的基础上,该功能有望提高效率和响应能力,使其成为 Java 不断发展的生态系统的重要补充。