1. Overview
1.概述
In this quick tutorial, we’ll demonstrate the basics of different JVM Garbage Collection (GC) implementations. Then we’ll learn how to enable a particular type of Garbage Collection in our applications.
在这个快速教程中,我们将展示不同的JVM垃圾收集(GC)实现的基本知识。然后我们将学习如何在我们的应用程序中启用特定类型的垃圾收集。
2. Brief Introduction to Garbage Collection
2.垃圾收集的简要介绍
Given the name, it seems like Garbage Collection would deal with finding and deleting the garbage from the memory. However, in reality, Garbage Collection tracks each and every object available in the JVM heap space, and removes the unused ones.
从名字上看,Garbage Collection似乎是在处理寻找和删除内存中的垃圾。然而,实际上,Garbage Collection跟踪JVM堆空间中的每一个可用对象,并删除未使用的对象。
Basically, GC works in two simple steps, known as Mark and Sweep:
基本上,GC在两个简单的步骤中工作,被称为标记和扫荡。
- Mark – this is where the garbage collector identifies which pieces of memory are in use and which aren’t.
- Sweep – this step removes objects identified during the “mark” phase.
Advantages:
优点:
- No manual memory allocation/deallocation handling because unused memory space is automatically handled by GC
- No overhead of handling Dangling Pointer
- Automatic Memory Leak management (GC on its own can’t guarantee the full proof solution to memory leaking; however, it takes care of a good portion of it)
Disadvantages:
弊端:
- Since JVM has to keep track of object reference creation/deletion, this activity requires more CPU power than the original application. It may affect the performance of requests which require large memory.
- Programmers have no control over the scheduling of CPU time dedicated to freeing objects that are no longer needed.
- Using some GC implementations might result in the application stopping unpredictably.
- Automatized memory management won’t be as efficient as the proper manual memory allocation/deallocation.
3. GC Implementations
3.GC的实施
JVM has five types of GC implementations:
JVM有五种类型的GC实现。
- Serial Garbage Collector
- Parallel Garbage Collector
- CMS Garbage Collector
- G1 Garbage Collector
- Z Garbage Collector
3.1. Serial Garbage Collector
3.1.串行垃圾收集器
This is the simplest GC implementation, as it basically works with a single thread. As a result, this GC implementation freezes all application threads when it runs. Therefore, it’s not a good idea to use it in multi-threaded applications, like server environments.
这是最简单的GC实现,因为它基本上只对一个线程工作。因此,这个GC实现在运行时冻结了所有应用线程。因此,在多线程应用程序中使用它并不是一个好主意,比如服务器环境。
However, there was an excellent talk given by Twitter engineers at QCon 2012 about the performance of Serial Garbage Collector, which is a good way to understand this collector better.
然而,Twitter工程师在QCon 2012上发表了一篇关于Serial Garbage Collector的性能的精彩演讲,这是更好地了解该收集器的一个好方法。
The Serial GC is the garbage collector of choice for most applications that don’t have small pause time requirements and run on client-style machines. To enable Serial Garbage Collector, we can use the following argument:
串行GC是大多数对暂停时间要求不高且运行在客户机上的应用程序的首选垃圾收集器。要启用Serial Garbage Collector,我们可以使用以下参数。
java -XX:+UseSerialGC -jar Application.java
3.2. Parallel Garbage Collector
3.2.并行垃圾收集器
It’s the default GC of the JVM, and sometimes called Throughput Collectors. Unlike Serial Garbage Collector, it uses multiple threads for managing heap space, but it also freezes other application threads while performing GC.
它是JVM的默认GC,有时也称为吞吐量收集器。与串行垃圾收集器不同,它使用多个线程来管理堆空间,但它也会在执行GC时冻结其他应用程序线程。
If we use this GC, we can specify maximum garbage collection threads and pause time, throughput, and footprint (heap size).
如果我们使用这个GC,我们可以指定最大的垃圾收集线程和暂停时间、吞吐量和足迹(堆大小)。
The numbers of garbage collector threads can be controlled with the command-line option -XX:ParallelGCThreads=<N>.
垃圾收集器线程的数量可以通过命令行选项-XX:ParallelGCThreads=<N>来控制。
The maximum pause time goal (gap [in milliseconds] between two GC) is specified with the command-line option -XX:MaxGCPauseMillis=<N>.
最大的暂停时间目标(两个GC之间的间隙[毫秒])是用命令行选项-XX:MaxGCPauseMillis=<N>/em>指定的。
The time spent doing garbage collection versus the time spent outside of garbage collection is called the maximum throughput target and can be specified by the command-line option -XX:GCTimeRatio=<N>.
进行垃圾收集的时间与垃圾收集之外的时间相比,被称为最大吞吐量目标,可以通过命令行选项-XX:GCTimeRatio=<N>.指定。
The maximum heap footprint (the amount of heap memory that a program requires while running) is specified using the option -Xmx<N>.
使用选项-Xmx<N>.来指定最大堆足迹(程序运行时需要的堆内存量)。
To enable Parallel Garbage Collector, we can use the following argument:
要启用并行垃圾收集器,我们可以使用以下参数。
java -XX:+UseParallelGC -jar Application.java
3.3. CMS Garbage Collector
3.3.CMS垃圾收集器
The Concurrent Mark Sweep (CMS) implementation uses multiple garbage collector threads for garbage collection. It’s designed for applications that prefer shorter garbage collection pauses, and can afford to share processor resources with the garbage collector while the application is running.
Concurrent Mark Sweep (CMS)实现使用多个垃圾收集器线程进行垃圾收集。它是为那些喜欢较短垃圾收集暂停时间的应用程序设计的,并且能够在应用程序运行时与垃圾收集器共享处理器资源。
Simply put, applications using this type of GC respond slower on average, but don’t stop responding to perform garbage collection.
简单地说,使用这种类型的GC的应用程序平均响应速度较慢,但不会停止响应以执行垃圾收集。
A quick point to note here is that since this GC is concurrent, an invocation of explicit garbage collection, such as using System.gc() while the concurrent process is working, will result in Concurrent Mode Failure / Interruption.
这里需要注意的一点是,由于这个GC是并发的,调用显式垃圾收集,例如在并发进程工作时使用System.gc(),将导致并发模式失败/中断。
If more than 98% of the total time is spent in CMS garbage collection, and less than 2% of the heap is recovered, then an OutOfMemoryError is thrown by the CMS collector. If necessary, we can disable this feature by adding the option -XX:-UseGCOverheadLimit to the command line.
如果在CMS的垃圾收集过程中花费了超过98%的时间,而被恢复的堆却少于2%,那么CMS的收集器就会抛出一个OutOfMemoryError。如果有必要,我们可以通过在命令行中添加选项-XX:-UseGCOverheadLimit来禁用这个功能。
This collector also has a mode known as an incremental mode, which is being deprecated in Java SE 8 and may be removed in a future major release.
这个收集器也有一个被称为增量模式的模式,这个模式在Java SE 8中被废弃了,可能会在未来的主要版本中被删除。
To enable the CMS Garbage Collector, we can use the following flag:
为了启用CMS垃圾收集器,我们可以使用以下标志。
java -XX:+UseParNewGC -jar Application.java
As of Java 9, the CMS garbage collector has been deprecated. Therefore, JVM prints a warning message if we try to use it:
从Java 9开始,CMS垃圾收集器已经被废弃了。因此,如果我们试图使用它,JVM会打印出一条警告信息。
>> java -XX:+UseConcMarkSweepGC --version
Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated
in version 9.0 and will likely be removed in a future release.
java version "9.0.1"
Moreover, Java 14 completely dropped the CMS support:
此外,Java 14完全放弃了对CMS的支持。
>> java -XX:+UseConcMarkSweepGC --version
OpenJDK 64-Bit Server VM warning: Ignoring option UseConcMarkSweepGC;
support was removed in 14.0
openjdk 14 2020-03-17
3.4. G1 Garbage Collector
3.4.G1垃圾收集器
G1 (Garbage First) Garbage Collector is designed for applications running on multi-processor machines with large memory space. It’s available from the JDK7 Update 4 and in later releases.
G1(Garbage First)垃圾收集器是为运行在具有大内存空间的多处理器机器上的应用程序设计的。它从JDK7 Update 4及以后的版本中可用。
G1 collector will replace the CMS collector, since it’s more performance efficient.
G1收集器将取代CMS收集器,因为它的性能更高效。
Unlike other collectors, the G1 collector partitions the heap into a set of equal-sized heap regions, each a contiguous range of virtual memory. When performing garbage collections, G1 shows a concurrent global marking phase (i.e. phase 1, known as Marking) to determine the liveness of objects throughout the heap.
与其他收集器不同,G1收集器将堆划分为一组大小相等的堆区域,每个堆区域是虚拟内存的连续范围。在执行垃圾收集时,G1显示了一个并发的全局标记阶段(即阶段1,称为标记),以确定整个堆中对象的有效性。
After the mark phase is complete, G1 knows which regions are mostly empty. It collects in these areas first, which usually yields a significant amount of free space (i.e. phase 2, known as Sweeping). That’s why this method of garbage collection is called Garbage-First.
标记阶段完成后,G1知道哪些区域大部分是空的。它首先在这些区域进行收集,这通常会产生大量的自由空间(即第二阶段,称为Sweeping)。这就是为什么这种垃圾收集方法被称为垃圾优先。
To enable the G1 Garbage Collector, we can use the following argument:
为了启用G1垃圾收集器,我们可以使用以下参数。
java -XX:+UseG1GC -jar Application.java
3.5. Java 8 Changes
3.5.Java 8的变化
Java 8u20 has introduced one more JVM parameter for reducing the unnecessary use of memory by creating too many instances of the same String. This optimizes the heap memory by removing duplicate String values to a global single char[] array.
Java 8u20又引入了一个JVM参数,用于减少因创建同一String的过多实例而造成的不必要的内存使用。这通过将重复的String值删除到一个全局的单一char[]数组来优化堆内存。
We can enable this parameter by adding -XX:+UseStringDeduplication as a JVM parameter.
我们可以通过添加-XX:+UseStringDeduplication作为JVM参数来启用这个参数。
3.6. Z Garbage Collector
3.6.Z垃圾收集器
ZGC (Z Garbage Collector) is a scalable low-latency garbage collector that debuted in Java 11 as an experimental option for Linux. JDK 14 introduced ZGC under the Windows and macOS operating systems. ZGC has obtained the production status from Java 15 onwards.
ZGC(Z垃圾收集器) 是一个可扩展的低延迟垃圾收集器,在Java 11中作为Linux的实验性选项首次亮相。JDK 14在Windows和macOS操作系统下引入了ZGC。ZGC从Java 15开始获得了生产状态。
ZGC performs all expensive work concurrently, without stopping the execution of application threads for more than 10 ms, which makes it suitable for applications that require low latency. It uses load barriers with colored pointers to perform concurrent operations when the threads are running, and they’re used to keep track of heap usage.
ZGC并发地执行所有昂贵的工作,不会停止应用线程的执行超过10毫秒,这使它适合于需要低延迟的应用。它使用带有彩色指针的负载屏障来执行线程运行时的并发操作,它们被用来跟踪堆的使用情况。
Reference coloring (colored pointers) is the core concept of ZGC. It means that ZGC uses some bits (metadata bits) of reference to mark the state of the object. It also handles heaps ranging from 8MB to 16TB in size. Furthermore, pause times don’t increase with the heap, live-set, or root-set size.
引用着色(彩色指针)是ZGC的核心概念。它意味着ZGC使用引用的一些位(元数据位)来标记对象的状态。它还可以处理从8MB到16TB大小的堆。此外,暂停时间不随堆、活集或根集大小而增加。
Similar to G1, Z Garbage Collector partitions the heap, except that heap regions can have different sizes.
与G1类似,Z垃圾收集器对堆进行分割,只是堆区域可以有不同的大小。
To enable the Z Garbage Collector, we can use the following argument in JDK versions lower than 15:
要启用Z垃圾收集器,我们可以在JDK低于15的版本中使用以下参数。
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC Application.java
From version 15 on, we don’t need experimental mode on:
从15版开始,我们不需要开启实验模式。
java -XX:+UseZGC Application.java
We should note that ZGC isn’t the default Garbage Collector.
我们应该注意,ZGC并不是默认的垃圾收集器。
4. Conclusion
4.结论
In this article, we looked at the different JVM Garbage Collection implementations and their use cases.
在这篇文章中,我们研究了不同的JVM垃圾收集实现和它们的使用情况。
More detailed documentation can be found here.
更详细的文件可以在这里找到。