1. 概述
在这个快速教程中,我们将演示不同JVM垃圾回收(GC)实现的基础知识。然后我们将学习如何在我们的应用程序中启用特定类型的垃圾回收器。
2. 垃圾回收简介
根据名称,垃圾收集似乎会处理从内存中查找和删除垃圾的问题。然而,实际上,垃圾收集会跟踪JVM堆空间中可用的每个对象,并删除未使用的对象。
基本上,GC的工作分为两个简单的步骤,称为标记和清除:
- 标记-这是垃圾收集器识别哪些内存正在使用,哪些没有使用
- 清除-此步骤删除在“标记”阶段识别的对象
优势:
缺点:
- 由于JVM必须跟踪对象引用的创建/删除,因此此活动需要比原始应用程序更多的CPU能力,它可能会影响需要大内存的请求的性能
- 程序员无法控制专用于释放不再需要的对象的CPU时间的调度
- 使用某些GC实现可能会导致应用程序意外停止
- 自动内存管理不会像正确的手动内存分配/解除分配那样高效
3. GC实现
JVM有四种GC实现方式:
- 串行垃圾收集器
- 并行垃圾收集器
- G1垃圾收集器
- ZGC
3.1 串行垃圾收集器
这是最简单的GC实现,因为它基本上使用单个线程。因此,这个GC实现在运行时会冻结所有应用程序线程。因此,在多线程应用程序(如服务器环境)中使用它不是一个好主意。
然而,在QCon 2012上,Twitter工程师们就串行垃圾收集器的性能做了一个很好的演讲,这是更好地理解这个收集器的好方法。
串行GC是大多数对暂停时间要求不高且运行在客户端类型机器上的应用程序的首选垃圾收集器。要启用串行垃圾收集器,我们可以使用以下参数:
java -XX:+UseSerialGC -jar Application.java
3.2 并行垃圾收集器
从Java 5到Java 8,它是JVM的默认GC,有时称为吞吐量收集器。与串行垃圾收集器不同,它使用多个线程来管理堆空间,但在执行GC时也会冻结其他应用程序线程。
如果我们使用这个GC,我们可以指定最大垃圾收集线程数和暂停时间、吞吐量和占用空间(堆大小)。
垃圾回收器线程数可以使用命令行选项-XX:ParallelGCThreads=<N>进行控制。
最大暂停时间目标(向垃圾收集器提示需要<N>毫秒或更短的暂停时间)通过命令行选项-XX:MaxGCPauseMillis=<N>指定。
进行垃圾收集所花费的时间与垃圾收集之外花费的时间称为最大吞吐量目标,可以通过命令行选项-XX:GCTimeRatio=<N>指定。
最大堆占用空间(程序运行时所需的堆内存量)使用选项-Xmx<N>指定。
要启用并行垃圾收集器,我们可以使用以下参数:
java -XX:+UseParallelGC -jar Application.java
3.3 G1垃圾收集器
G1(Garbage First)垃圾收集器专为运行在具有大内存空间的多处理器机器上的应用程序而设计,它可从JDK7 Update 4和更高版本中获得。
与其他收集器不同,G1收集器将堆划分为一组大小相等的堆区域,每个区域都是连续的虚拟内存范围。在执行垃圾回收时,G1会显示一个并发的全局标记阶段(即阶段1,称为标记)来确定整个堆中对象的活跃度。
标记阶段完成后,G1知道哪些区域大部分是空的。它首先在这些区域收集数据,这通常会产生大量可用空间(即第2阶段,称为清理)。这就是为什么这种垃圾收集方法被称为垃圾优先的原因。
要启用G1垃圾收集器,我们可以使用以下参数:
java -XX:+UseG1GC -jar Application.java
3.4 Java 8的变化
Java 8u20引入了另一个JVM参数,用于通过创建相同字符串的过多实例来减少不必要的内存使用。这通过将重复的String值删除到全局单个char[]数组来优化堆内存。
我们可以通过添加-XX:+UseStringDeduplication作为JVM参数来启用此参数。
3.5 ZGC
ZGC(Z Garbage Collector)是一种可扩展的低延迟垃圾收集器,作为Linux的实验性选项在Java 11中首次亮相。JDK 14在Windows和macOS操作系统下引入了ZGC,并从Java 15开始获得生产状态。
ZGC并发执行所有昂贵的工作,不会停止应用程序线程的执行超过10毫秒,这使其适用于需要低延迟的应用程序。它使用带有彩色指针的负载屏障在线程运行时执行并发操作,并用于跟踪堆使用情况。
引用着色(彩色指针)是ZGC的核心概念,这意味着ZGC使用引用的一些位(元数据位)来标记对象的状态。它还可以处理大小从8MB到16TB不等的堆。此外,暂停时间不会随着堆、活动集或根集大小的增加而增加。
与G1类似,ZGC对堆进行分区,只是堆区域可以有不同的大小。
要启用ZGC,我们可以在低于15的JDK版本中使用以下参数:
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC Application.java
从版本15开始,我们不需要实验模式:
java -XX:+UseZGC Application.java
我们应该注意到ZGC不是默认的垃圾收集器。
4. 总结
在本文中,我们研究了不同的JVM垃圾收集实现及其用例。
可以在此处找到更详细的文档。
Post Directory
