做电影下载网站,京津冀协同发展的问题,淮安 网站建设,注册自己的网站码到三十五 #xff1a; 个人主页 心中有诗画#xff0c;指尖舞代码#xff0c;目光览世界#xff0c;步履越千山#xff0c;人间尽值得 ! 在Java虚拟机#xff08;JVM#xff09;中#xff0c;垃圾收集#xff08;GC#xff09;是一个自动管理内存的过程#xff… 码到三十五 个人主页 心中有诗画指尖舞代码目光览世界步履越千山人间尽值得 ! 在Java虚拟机JVM中垃圾收集GC是一个自动管理内存的过程旨在回收不再使用的对象所占用的内存空间。G1垃圾收集器G1 GC是JVM中的一种重要垃圾收集器尤其适用于需要低延迟和可预测停顿时间的大型应用程序。本文将深入探讨G1垃圾收集器的工作原理、关键特性和性能优化建议。 目录 一、G1收集器概述主要特点 二、G1分区划分三、为什么G1收集器需要设计巨型对象四、G1收集器的回收过程五、G1的两种回收策略5.1 Young GC新生代回收5.2 Mix GC混合回收 六、跨代引用和RSet记忆集七、性能优化建议八、G1核心配置参数九、结语 一、G1收集器概述
G1收集器Garbage-First Garbage Collector简称G1 GC是Java虚拟机JVM中的一种垃圾收集器专为服务器端应用设计特别适用于具有多核处理器和大内存的机器。G1 GC在JDK 7u4版本中被正式推出并且在JDK 9中成为默认的垃圾收集器。它的主要目标是在满足高吞吐量的同时尽可能缩短垃圾收集造成的停顿时间。
主要特点
并行与并发G1 GC能够充分利用多核处理器的优势通过并行执行垃圾收集任务来提高效率。同时它的大部分工作都是与应用线程并发执行的从而减少了停顿时间。分区域收集G1 GC将整个堆内存划分为多个大小相等的独立区域Region这些区域在逻辑上是连续的但在物理内存上可能不是连续的。每个Region都可以扮演Eden区、Survivor区或Old区等角色。这种设计使得G1 GC能够更加灵活地进行内存管理和垃圾收集。优先回收垃圾最多区域G1 GC通过跟踪每个Region中的垃圾堆积情况并根据回收价值和成本进行排序优先回收垃圾最多的Region。这种策略有助于最大限度地提高垃圾收集的效率。可预测的停顿时间G1 GC通过建立一个可预测的停顿时间模型允许用户明确指定在一个特定时间片段内垃圾收集所造成的停顿时间不得超过某个阈值。这使得G1 GC非常适合需要严格控制停顿时间的应用场景。使用标记-整理算法在整体上G1 GC使用标记-整理算法来回收内存以减少内存碎片的产生。但在两个Region之间进行垃圾收集时它则采用标记-复制算法。这种组合策略有助于兼顾内存利用率和垃圾收集效率。
二、G1分区划分
G1收集器的分区划分是其核心特性之一它允许G1更灵活、高效地管理内存和执行垃圾回收 基本思想 G1收集器将整个Java堆划分为多个大小相等、独立的区域这些区域被称为“Region”。每个Region的大小可以根据堆空间的实际大小而定通常在1MB到32MB之间且必须是2的N次幂。这意味着Region的大小可以是1MB、2MB、4MB、8MB、16MB或32MB。默认情况下整个堆空间被划分为约2048个这样的Region。 分区类型 G1的Region可以根据其用途和状态分为不同类型。主要包括 自由分区Free Heap Region, FHR这些Region当前没有包含任何对象是空闲的可以用于新的对象分配。新生代分区Young Heap Region, YHR这些Region被划分为新生代包括Eden区和Survivor区。新生代分区主要用于存储新创建的对象。大对象分区Humongous Heap Region, HHR专门用于存储大对象。在G1中只要对象的大小超过了一个Region容量的一半就被认为是大对象。这些对象会被直接分配到Humongous Region中且每个大对象都单独占用一个或多个连续的Humongous Region。老年代分区Old Heap Region, OHR这些Region被划分为老年代用于存储长时间存活的对象。 分区的管理和回收 G1收集器通过维护一个优先列表来跟踪各个Region中的垃圾堆积情况和回收价值。在垃圾回收过程中G1会根据这个列表优先回收价值最大的Region。这种策略使得G1能够更有效地利用处理器资源并最大限度地减少垃圾回收造成的停顿时间。 优点 G1的分区划分带来了几个显著优点。首先它允许更细粒度的内存管理提高了内存的利用率。其次通过优先回收垃圾最多的RegionG1能够保持较高的吞吐量并缩短停顿时间。最后G1的分区策略使其能够很好地适应不同的内存大小和垃圾回收需求。
三、为什么G1收集器需要设计巨型对象
G1收集器需要设计巨型对象Humongous Objects主要是出于对内存管理和垃圾收集效率的考虑。在G1收集器的设计中整个堆内存被划分为多个大小相等的区域Region每个Region用于存放对象。然而有些对象的大小可能会超过一个Region的容量这就引出了巨型对象的概念。
巨型对象是指那些大小超过了一个Region容量50%以上的对象。由于这些对象太大无法完整地存放在一个Region中因此需要特殊处理。G1收集器通过引入巨型对象的概念并为之设计专门的存储和管理机制确保了这些大对象能够被有效地管理和回收。
具体来说巨型对象在G1中被直接分配到特殊的Humongous Region中每个巨型对象可以独占一个或多个连续的Humongous Region。这样做的好处是可以避免由于对象跨Region存储而导致的复杂性和性能开销。同时G1收集器还会针对巨型对象进行特殊的垃圾回收策略以提高垃圾收集的效率和整个系统的性能。
此外巨型对象的设计也考虑到了应用的实际情况和需求。在实际应用中往往存在一些需要占用大量内存的大对象如大型的数组、数据结构等。如果不对这些大对象进行特殊处理它们可能会对整个垃圾收集器的性能和内存利用率造成负面影响。因此G1收集器通过设计巨型对象及其管理机制来应对这一挑战。
综上所述G1收集器需要设计巨型对象主要是为了更有效地管理大内存对象提高垃圾收集效率和整个系统的性能。
四、G1收集器的回收过程
G1收集器的回收过程主要包括以下几个步骤 初始标记Initial Marking 这个过程是STWStop-The-World的但通常耗时非常短。它标记出从GC Roots直接可达的对象作为后续垃圾收集的基础。 并发标记Concurrent Marking 在初始标记完成后G1 GC会进入并发标记阶段。这个阶段与应用程序线程并发执行通过递归地追踪所有可达的对象并将它们标记为存活。这个过程是并发的因此不会阻塞应用程序的执行。 最终标记Final Marking 为了处理在并发标记过程中新产生的对象引用关系G1 GC会执行一次短暂的STW的最终标记。这个阶段确保所有在并发标记阶段漏掉的对象都被正确标记。 筛选回收Live Data Counting and Evacuation 在这个阶段G1 GC会根据每个Region的垃圾堆积情况和回收价值进行排序并选择性地回收部分Region中的垃圾对象。回收过程包括将存活的对象从一个Region复制或移动到另一个Region并更新相关的引用。这个过程也是并发的旨在最大限度地减少停顿时间。同时这个阶段可能会涉及到对象的整理和压缩以减少内存碎片。
此外G1收集器还采用了分区Region的方式来管理内存每个Region都被标记了不同的状态如Eden、Survivor、Old等。这种设计使得G1能够更灵活地进行内存分配和垃圾回收从而提高了整体的效率和性能。
值得注意的是G1收集器还提供了两种主要的垃圾回收模式Young GC和Mixed GC。Young GC主要负责回收新生代中的垃圾对象而Mixed GC则负责回收新生代和部分老年代中的垃圾对象。这两种模式都是根据堆内存的使用情况和GC的触发条件来自动选择的。
五、G1的两种回收策略
G1垃圾收集器是Java虚拟机JVM中的一个重要组件它提供了两种主要的垃圾回收策略Young GC新生代回收和Mix GC混合回收。这两种策略在回收对象和回收区域上有所不同但都是为了提高垃圾回收的效率减少停顿时间从而提升应用程序的性能。
5.1 Young GC新生代回收
Young GC主要负责回收新生代中的对象。新生代通常包含新创建的对象这些对象更有可能在短时间内变成垃圾。Young GC的执行过程相对较快因为它只涉及新生代中对象的扫描和回收。
在Young GC过程中Eden区和Survivor区的存活对象会被复制到另一个Survivor区或者晋升到老年代。这个过程是Stop-The-WorldSTW的意味着在回收过程中应用程序的所有线程都会被暂停。但是由于新生代中的对象通常较少因此这个暂停时间通常较短对应用程序的性能影响也较小。
5.2 Mix GC混合回收
Mix GC则是G1收集器特有的回收策略它不仅回收新生代中的所有Region还会回收部分老年代中的Region。这种策略的目标是在保证停顿时间不超过预期的情况下尽可能地回收更多的垃圾对象。
在Mix GC过程中首先会进行全局并发标记global concurrent marking这个过程是并发的与应用程序线程同时执行用于标记出所有存活的对象。然后在回收阶段G1会根据标记结果选择收益较高的部分老年代Region和新生代Region一起进行回收。这个选择过程是基于对Region中垃圾对象的数量和回收价值的评估。
与Young GC不同Mix GC的停顿时间可能会更长因为它涉及到对老年代中对象的扫描和回收。但是由于Mix GC能够回收更多的垃圾对象因此它通常能够更有效地释放内存空间减少垃圾堆积对应用程序性能的影响。
六、跨代引用和RSet记忆集
在垃圾收集过程中跨代引用或跨Region引用是一个需要特别注意的现象 跨代引用的概念 在垃圾收集领域跨代引用指的是不同代际之间的对象相互引用。在G1收集器中由于堆被划分为多个Region跨代引用通常表现为跨Region引用。年轻代指向老年代的引用在垃圾收集中不是主要问题因为即使年轻代的对象被清理程序仍然可以正常运行且未被标记到的老年代对象会在后续的Major GC中被回收。 老年代指向年轻代的引用问题 当存在老年代指向年轻代的引用时情况就复杂了。在Minor GC阶段我们不能简单地清理年轻代中的对象因为老年代中可能还有对象持有对这些对象的引用。为了解决这个问题我们需要一种机制来跟踪这些跨Region的引用。 RSet记忆集的作用 RSet正是为了解决这个问题而设计的。它的主要作用是记录哪些Region中的老年代对象有指向年轻代的引用。在GC时通过扫描这些Region中的RSet我们可以快速识别出需要保留的年轻代对象从而避免扫描整个老年代显著提高了垃圾收集的效率。RSet的实现本质上是一种哈希表其中Key是Region的起始地址Value是一个集合存储了卡表的索引号。 RSetRememberedSet是一个非常重要的数据结构用于记录并跟踪其他Region指向当前Region中对象的引用。在G1收集器的分区模型中由于堆内存被划分为多个独立的Region对象之间的引用关系可能跨越不同的Region。为了能够在垃圾收集过程中正确地识别和处理这些跨Region的引用G1引入了RSet的概念。 每个Region都有一个与之关联的RSet用于记录其他Region中指向该Region内对象的引用信息。当发生对象引用关系变化时G1会更新相应的RSet以确保垃圾收集的准确性。在垃圾收集过程中G1会利用RSet来快速确定哪些Region之间存在引用关系从而避免不必要的全堆扫描提高垃圾收集的效率。 RSet的实现通常涉及一些优化技术如使用位图Bitmaps或压缩表CompressedTables来紧凑地存储引用信息以减少内存占用和提高访问速度。此外G1还采用了一些策略来维护RSet的一致性如在并发标记阶段使用写屏障Write Barriers来拦截并更新跨Region的引用。 减少YGC时的扫描开销 由于新生代的垃圾收集通常很频繁即YGC如果每次都需要扫描整个老年代来确定是否有对新生代的引用那么开销将会非常大。通过RSet的跟踪机制我们可以精确地知道哪些老年代Region中的对象引用了新生代对象从而只扫描这些Region大大降低了YGC时的扫描开销。 卡标记Card Marking技术与卡表Card Table HotSpot JVM为了更高效地处理老年代到新生代的引用问题采用了卡标记技术。具体来说它使用了一个称为卡表Card Table的数据结构来辅助标记过程。堆空间被划分为一系列的卡页Card Page每个卡页对应卡表中的一个标记项。当发生对老年代到新生代引用的写操作时通过写屏障Write Barrier机制来更新卡表中对应的标记项。这样在GC时我们只需要扫描那些被标记为dirty的卡页所对应的Region即可快速找到所有老年代到新生代的引用关系。
七、性能优化建议 合理设置堆大小根据应用程序的内存需求和硬件资源合理设置JVM的堆大小。过大的堆可能会导致长时间的垃圾收集停顿而过小的堆则可能导致频繁的垃圾收集。 调整停顿时间目标通过调整G1的停顿时间目标-XX:MaxGCPauseMillis参数可以平衡垃圾收集的效率和应用程序的响应时间。在需要低延迟的场景中可以设置较短的停顿时间目标。 启用并行垃圾收集线程通过增加并行垃圾收集线程的数量-XX:ParallelGCThreads参数可以提高垃圾收集的效率。然而过多的线程可能会导致系统资源的竞争和额外的开销因此需要谨慎调整。 优化对象分配和晋升策略通过优化对象的分配和晋升策略可以减少新生代和老年代之间的对象流动从而降低垃圾收集的开销。例如可以考虑使用对象池、缓存等技术来减少临时对象的创建和销毁。 监控和分析GC日志定期监控和分析GC日志可以帮助识别潜在的内存泄漏、性能瓶颈和优化机会。可以使用JVM自带的工具如jstat、jvisualvm或第三方工具如GCViewer、YourKit来进行日志分析和性能调优。
八、G1核心配置参数
在JDK9及以后的版本中G1是默认的垃圾收集器但在JDK8中你需要显式地启用。以下是G1收集器的一些核心配置参数 -XX:UseG1GC: 这个参数用于启用G1垃圾收集器。在JDK8中你需要明确设置这个参数来使用G1而在JDK9及更高版本中G1是默认启用的。 -XX:G1HeapRegionSize: 这个参数用于设置每个Region的大小。Region是G1收集器管理内存的基本单位。该值必须是2的幂范围在1MB到32MB之间。G1的目标是根据最小的Java堆大小划分出约2048个这样的区域。默认情况下这个值是堆内存的1/2000这意味着G1收集器管理的最小堆内存应该是2GB以上最大堆内存为64GB。 -XX:MaxGCPauseMillis: 这个参数用于设置期望的最大GC停顿时间指标。G1收集器会尽力在这个时间内完成垃圾回收以减少应用程序的停顿时间。默认值是200毫秒。 -XX:ParallelGCThreads: 这个参数用于设置并行垃圾回收的线程数。这个值通常设置为与可用的CPU核心数相等最大可以设置为8。 -XX:ConcGCThreads: 这个参数用于设置并发标记的线程数。并发标记是G1收集器在垃圾回收过程中的一个阶段这个阶段与应用程序线程并发执行。通常这个值设置为并行垃圾回收线程数ParallelGCThreads的1/4左右。 -XX:InitiatingHeapOccupancyPercent: 这个参数用于设置触发并发GC周期的Java堆占用率阈值。当堆内存的占用率达到这个值时G1收集器会启动一个并发GC周期。默认值是45%这意味着当堆内存的45%被占用时就会触发垃圾回收。 -XX:PrintGCDetails 和 -verbose:gc: 这两个参数不是G1特有的但它们对于调试和监控垃圾收集器的行为非常有用。-XX:PrintGCDetails会打印详细的垃圾收集日志包括每次垃圾收集的时间、回收的对象数量等信息。-verbose:gc则会启用垃圾收集的日志记录通常与-XX:PrintGCDetails一起使用以获取更全面的日志输出。 九、结语
G1垃圾收集器以其可预测的停顿时间、灵活的内存管理和高效的并发标记等特点在JVM中占据了重要的地位。通过深入理解G1的工作原理和关键特性并根据实际应用场景进行性能优化我们可以更好地利用G1来提升Java应用程序的性能和响应时间。 听说...关注下面公众号的人都变牛了纯技术纯干货 !