精华内容
下载资源
问答
  • G1收集器

    2019-12-22 17:00:42
    G1收集器 一.定义 开启选项:-XX:+UseG1GC ​ G1垃圾收集器也是以关注延迟为目标、服务器端应用的垃圾收集器,被HotSpot团队寄予取代CMS的使命,也是一个非常具有调优潜力的垃圾收集器。虽然G1也有类似CMS的收集...

    G1收集器

    一.定义

    开启选项:-XX:+UseG1GC
    

    ​ G1垃圾收集器也是以关注延迟为目标、服务器端应用的垃圾收集器,被HotSpot团队寄予取代CMS的使命,也是一个非常具有调优潜力的垃圾收集器。虽然G1也有类似CMS的收集动作:初始标记、并发标记、重新标记、清除、转移回收,并且也以一个串行收集器做担保机制,但单纯地以类似前三种的过程描述显得并不是很妥当。事实上,G1收集与以上三组收集器有很大不同:

    1. G1的设计原则是"首先收集尽可能多的垃圾(Garbage First)"。因此,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部采用了启发式算法,在老年代找出具有高收集收益的分区进行收集。同时G1可以根据用户设置的暂停时间目标自动调整年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;
    2. G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);
    3. G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;
    4. G1的收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集),这样即使堆内存很大时,也可以限制收集范围,从而降低停顿。

    二.内存模型

    G1分区示意图

    1.分区 Region

    ​ G1采用了分区(Region)的思路,将整个堆空间分成若干个大小相等的内存区域,每次分配对象空间将逐段地使用内存。因此,在堆的使用上,G1并不要求对象的存储一定是物理上连续的,只要逻辑上连续即可;每个分区也不会确定地为某个代服务,可以按需在年轻代和老年代之间切换。启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区。

    2.卡片 Card

    ​ 在每个分区内部又被分成了若干个大小为512 Byte卡片(Card),标识堆内存最小可用粒度所有分区的卡片将会记录在全局卡片表(Global Card Table)中,分配的对象会占用物理上连续的若干个卡片,当查找对分区内对象的引用时便可通过记录卡片来查找该引用对象(见RSet)。每次对内存的回收,都是对指定分区的卡片进行处理。

    3.堆 Heap

    ​ G1同样可以通过-Xms/-Xmx来指定堆空间大小。当发生年轻代收集或混合收集时,通过计算GC与应用的耗费时间比,自动调整堆空间大小。

    ​ 如果GC频率太高,则通过增加堆尺寸,来减少GC频率,相应地GC占用的时间也随之降低。

    ​ 目标参数 -XX:GCTimeRatio 为GC与应用的耗费时间比,G1默认为9,而CMS默认为99。因为CMS的设计原则是耗费在GC上的时间尽可能的少。

    ​ 另外,当空间不足,如对象空间分配或转移失败时,G1会首先尝试增加堆空间,如果扩容失败,则发起担保的Full GC。Full GC后,堆尺寸计算结果也会调整堆空间。

    4.分代 Generation

    ​ 分代垃圾收集可以将关注点集中在最近被分配的对象上,而无需整堆扫描,避免长命对象的拷贝,同时独立收集有助于降低响应时间。虽然分区使得内存分配不再要求紧凑的内存空间,但G1依然使用了分代的思想。与其他垃圾收集器类似,G1将内存在逻辑上划分为年轻代和老年代,其中年轻代又划分为Eden空间和Survivor空间。但年轻代空间并不是固定不变的,当现有年轻代分区占满时,JVM会分配新的空闲分区加入到年轻代空间。

    ​ 整个年轻代内存会在初始空间-XX:G1NewSizePercent(默认整堆5%)与最大空间-XX:G1MaxNewSizePercent(默认60%)之间动态变化,且由参数目标暂停时间-XX:MaxGCPauseMillis(默认200ms)、需要扩缩容的大小以及分区的已记忆集合(RSet)计算得到。当然,G1依然可以设置固定的年轻代大小(参数-XX:NewRatio、-Xmn),但同时暂停目标将失去意义。
    G1的分代模型

    5.本地分配缓冲 Local allocation buffer

    ​ 由于分区的思想,每个线程均可以"认领"某个分区用于线程本地的内存分配,而不需要顾及分区是否连续。因此,每个应用线程和GC线程都会独立的使用分区,进而减少同步时间,提升GC效率,这个分区称为本地分配缓冲区(Lab)。

    ​ 其中,应用线程可以独占一个本地缓冲区(TLAB)来创建的对象,而大部分都会落入Eden区域(巨型对象或分配失败除外),因此TLAB的分区属于Eden空间;而每次垃圾收集时,每个GC线程同样可以独占一个本地缓冲区(GCLAB)用来转移对象,每次回收会将对象复制到Suvivor空间或老年代空间;对于从Eden/Survivor空间晋升(Promotion)到Survivor/老年代空间的对象,同样有GC独占的本地缓冲区进行操作,该部分称为晋升本地缓冲区(PLAB)。

    6.巨型对象 Humongous Region

    ​ 大小达到甚至超过分区大小一半的对象称为巨型对象。因为移动成本很高,所以在分配的时候会直接在老年代分配,其所占用的连续空间被称为巨型分区。G1内部做了一个优化,一旦发现没有引用指向巨型对象,则可直接在年轻代收集周期中被回收。

    ​ 应用程序应避免生成巨型对象。

    7.已记忆集合

    ​ G1为了避免STW式的整堆扫描,在每个分区记录了一个已记忆集合(RSet),内部类似一个反向指针,记录引用分区内对象的卡片索引。当要回收该分区时,通过扫描分区的RSet,来确定引用本分区内的对象是否存活,进而确定本分区内的对象存活情况。

    8.Per Region Table

    ​ RSet在内部使用Per Region Table(PRT)记录分区的引用情况。由于RSet的记录要占用分区的空间,如果一个分区非常"受欢迎",那么RSet占用的空间会上升,从而降低分区的可用空间。G1应对这个问题采用了改变RSet的密度的方式,在PRT中将会以三种模式记录引用:

    • 稀少:直接记录引用对象的卡片索引
    • 细粒度:记录引用对象的分区索引
    • 粗粒度:只记录引用情况,每个分区对应一个比特位

    ​ 由上可知,粗粒度的PRT只是记录了引用数量,需要通过整堆扫描才能找出所有引用,因此扫描速度也是最慢的。

    9.收集集合 CSet

    ​ 收集集合(CSet)代表每次GC暂停时回收的一系列目标分区。在任意一次收集暂停中,CSet所有分区都会被释放,内部存活的对象都会被转移到分配的空闲分区中。因此无论是年轻代收集,还是混合收集,工作的机制都是一致的。年轻代收集CSet只容纳年轻代分区,而混合收集会通过启发式算法,在老年代候选回收分区中,筛选出回收收益最高的分区添加到CSet中。

    ​ 候选老年代分区的CSet准入条件,可以通过活跃度阈值-XX:G1MixedGCLiveThresholdPercent(默认85%)进行设置,从而拦截那些回收开销巨大的对象;同时,每次混合收集可以包含候选老年代分区,可根据CSet对堆的总大小占比-XX:G1OldCSetRegionThresholdPercent(默认10%)设置数量上限。

    9.1.年轻代收集集合

    ​ 应用线程不断活动后,年轻代空间会被逐渐填满。当JVM分配对象到Eden区域失败(Eden区已满)时,便会触发一次STW式的年轻代收集。在年轻代收集中,Eden分区存活的对象将被拷贝到Survivor分区;原有Survivor分区存活的对象,将根据任期阈值(tenuring threshold)分别晋升到PLAB中,新的survivor分区和老年代分区。而原有的年轻代分区将被整体回收掉。

    ​ 同时,年轻代收集还负责维护对象的年龄(存活次数),辅助判断老化(tenuring)对象晋升的时候是到Survivor分区还是到老年代分区。年轻代收集首先先将晋升对象尺寸总和、对象年龄信息维护到年龄表中,再根据年龄表、Survivor尺寸、Survivor填充容量-XX:TargetSurvivorRatio(默认50%)、最大任期阈值-XX:MaxTenuringThreshold(默认15),计算出一个恰当的任期阈值,凡是超过任期阈值的对象都会被晋升到老年代。

    9.2.混合收集集合

    ​ 年轻代收集不断活动后,老年代的空间也会被逐渐填充。当老年代占用空间超过整堆比IHOP阈值-XX:InitiatingHeapOccupancyPercent(默认45%)时,G1就会启动一次混合垃圾收集周期。为了满足暂停目标,G1可能不能一口气将所有的候选分区收集掉,因此G1可能会产生连续多次的混合收集与应用线程交替执行,每次STW的混合收集与年轻代收集过程相类似。

    ​ 为了确定包含到年轻代收集集合CSet的老年代分区,JVM通过参数混合周期的最大总次数-XX:G1MixedGCCountTarget(默认8)、堆废物百分比-XX:G1HeapWastePercent(默认5%)。通过候选老年代分区总数与混合周期最大总次数,确定每次包含到CSet的最小分区数量;根据堆废物百分比,当收集达到参数时,不再启动新的混合收集。而每次添加到CSet的分区,则通过计算得到的GC效率进行安排。

    年轻代收集与混合收集没有明显的不同,最大的区别在于两种收集的触发条件。

    三.活动周期

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1xiq0LaL-1577005221083)(https://c1.staticflickr.com/5/4760/28345835879_aa538bdcdf_b.jpg)]

    1.并发优化线程 Concurrence Refinement Threads

    ​ 并发优化线程,只专注扫描日志缓冲区记录的卡片来维护更新RSet。并发优化线程永远是活跃的,一旦发现全局列表有记录存在,就开始并发处理。如果记录增长很快或者来不及处理,那么通过阈值,G1会用分层的方式调度,使更多的线程处理全局列表。如果并发优化线程也不能跟上缓冲区数量,则Mutator线程(Java应用线程)会挂起应用并被加进来帮助处理,直到全部处理完。因此,必须避免此类场景出现。

    2.年轻代收集 Young Collection

    ​ 每次收集过程中,既有并行执行的活动,也有串行执行的活动,但都可以是多线程的。在并行执行的任务中,如果某个任务过重,会导致其他线程在等待某项任务的处理,需要对这些地方进行优化。

    3.并发标记 Concurrent Marking

    ​ 和应用线程并发执行,并发标记线程在并发标记阶段启动,由参数-XX:ConcGCThreads(默认GC线程数的1/4,即-XX:ParallelGCThreads/4)控制启动数量,每个线程每次只扫描一个分区,从而标记出存活对象图。

    ​ 在这一阶段会处理Previous/Next标记位图,扫描标记对象的引用字段。同时,并发标记线程还会定期检查和处理STAB全局缓冲区列表的记录,更新对象引用信息。参数-XX:+ClassUnloadingWithConcurrentMark会开启一个优化,如果一个类不可达(不是对象不可达),则在重新标记阶段,这个类就会被直接卸载。

    ​ 所有的标记任务必须在堆满前就完成扫描,如果并发标记耗时很长,那么有可能在并发标记过程中,又经历了几次年轻代收集。如果堆满前没有完成标记任务,则会触发担保机制,经历一次长时间的串行Full GC。

    4.重新标记 Remark

    ​ 重新标记(Remark)是最后一个标记阶段。在该阶段中,G1需要一个暂停的时间,去处理剩下的SATB日志缓冲区和所有更新,找出所有未被访问的存活对象,同时安全完成存活数据计算。这个阶段也是并行执行的,通过参数-XX:ParallelGCThread可设置GC暂停时可用的GC线程数。

    ​ 同时,引用处理也是重新标记阶段的一部分,所有重度使用引用对象(弱引用、软引用、虚引用、最终引用)的应用都会在引用处理上产生开销。

    5.清除 Cleanup

    ​ 紧挨着重新标记阶段的清除(Clean)阶段也是STW的。Previous/Next标记位图、以及PTAMS/NTAMS,都会在清除阶段交换角色。清除阶段主要执行以下操作:

    • RSet梳理,启发式算法会根据活跃度和RSet尺寸对分区定义不同等级,同时RSet数理也有助于发现无用的引用。参数-XX:+PrintAdaptiveSizePolicy可以开启打印启发式算法决策细节。
    • 整理堆分区,为混合收集周期识别回收收益高(基于释放空间和暂停目标)的老年代分区集合。
    • 识别所有空闲分区,即发现无存活对象的分区。该分区可在清除阶段直接回收,无需等待下次收集周期。

    5.年轻代收集/混合收集周期

    ​ 年轻代收集和混合收集周期,是G1回收空间的主要活动。当应用运行开始时,堆内存可用空间还比较大,只会在年轻代满时,触发年轻代收集;随着老年代内存增长,当到达IHOP阈值(老年代占整堆比,默认45%)时,G1开始着手准备收集老年代空间。

    1. 经历并发标记周期,识别出高收益的老年代分区。
    2. G1并不会马上开始一次混合收集,而是让应用线程先运行一段时间,等待触发一次年轻代收集。在这次STW中,G1将保准整理混合收集周期。
    3. 让应用线程运行,当接下来的几次年轻代收集时,将会有老年代分区加入到CSet中,即触发混合收集。

    这些连续多次的混合收集称为混合收集周期(Mixed Collection Cycle)。

    5.1并行活动

    • 外部根分区扫描 Ext Root Scanning:此活动对堆外的根(JVM系统目录、VM数据结构、JNI线程句柄、硬件寄存器、全局变量、线程对栈根)进行扫描,发现那些没有加入到暂停收集集合CSet中的对象。如果系统目录(单根)拥有大量加载的类,最终可能其他并行活动结束后,该活动依然没有结束而带来的等待时间。
    • 更新已记忆集合 Update RS:并发优化线程会对脏卡片的分区进行扫描更新日志缓冲区来更新RSet,但只会处理全局缓冲列表。作为补充,所有被记录但是还没有被优化线程处理的剩余缓冲区,会在该阶段处理,变成已处理缓冲区(Processed Buffers)。为了限制花在更新RSet的时间,可以设置暂停占用百分比-XX:G1RSetUpdatingPauseTimePercent(默认10%,即-XX:MaxGCPauseMills/10)。如果更新日志缓冲区更新的任务不降低,单纯地减少RSet的更新时间,会导致暂停中被处理的缓冲区减少,将日志缓冲区更新工作推到并发优化线程上,从而增加对Java应用线程资源的争夺。
    • RSet扫描 Scan RS:在收集当前CSet之前,考虑到分区外的引用,必须扫描CSet分区的RSet。如果RSet发生粗化,则会增加RSet的扫描时间。开启诊断模式-XX:UnlockDiagnosticVMOptions后,通过参数-XX:+G1SummarizeRSetStats可以确定并发优化线程是否能够及时处理更新日志缓冲区,并提供更多的信息,来帮助为RSet粗化总数提供窗口。参数-XX:G1SummarizeRSetStatsPeriod=n可设置RSet的统计周期,即经历多少此GC后进行一次统计
    • 代码根扫描 Code Root Scanning:对代码根集合进行扫描,扫描JVM编译后代码Native Method的引用信息(nmethod扫描),进行RSet扫描。事实上,只有CSet分区中的RSet有强代码根时,才会做nmethod扫描,查找对CSet的引用。
    • 转移和回收 Object Copy:通过选定的CSet以及CSet分区完整的引用集,将执行暂停时间的主要部分:CSet分区存活对象的转移、CSet分区空间的回收。通过工作窃取机制来负载均衡地选定复制对象的线程,并且复制和扫描对象被转移的存活对象将拷贝到每个GC线程分配缓冲区GCLAB。G1会通过计算,预测分区复制所花费的时间,从而调整年轻代的尺寸。
    • 终止 Termination:完成上述任务后,如果任务队列已空,则工作线程会发起终止要求。如果还有其他线程继续工作,空闲的线程会通过工作窃取机制尝试帮助其他线程处理。而单独执行根分区扫描的线程,如果任务过重,最终会晚于终止。

    5.2串行活动

    • 代码根更新 Code Root Fixup:根据转移对象更新代码根。
    • 代码根清理 Code Root Purge:清理代码根集合表。
    • 清除全局卡片标记 Clear CT:在任意收集周期会扫描CSet与RSet记录的PRT,扫描时会在全局卡片表中进行标记,防止重复扫描。在收集周期的最后将会清除全局卡片表中的已扫描标志。
    • 选择下次收集集合 Choose CSet:该部分主要用于并发标记周期后的年轻代收集、以及混合收集中,在这些收集过程中,由于有老年代候选分区的加入,往往需要对下次收集的范围做出界定;但单纯的年轻代收集中,所有收集的分区都会被收集,不存在选择。
    • 引用处理 Ref Proc:主要针对软引用、弱引用、虚引用、final引用、JNI引用。当Ref Proc占用时间过多时,可选择使用参数-XX:ParallelRefProcEnabled激活多线程引用处理。G1希望应用能小心使用软引用,因为软引用会一直占据内存空间直到空间耗尽时被Full GC回收掉;即使未发生Full GC,软引用对内存的占用,也会导致GC次数的增加。
    • 引用排队 Ref Enq:此项活动可能会导致RSet的更新,此时会通过记录日志,将关联的卡片标记为脏卡片。
    • 卡片重新脏化 Redirty Cards:重新脏化卡片。
    • 回收空闲巨型分区 Humongous Reclaim:G1做了一个优化:通过查看所有根对象以及年轻代分区的RSet,如果确定RSet中巨型对象没有任何引用,则说明G1发现了一个不可达的巨型对象,该对象分区会被回收。
    • 释放分区 Free CSet:回收CSet分区的所有空间,并加入到空闲分区中。

    6.转移失败的担保机制 Full GC

    ​ 转移失败(Evacuation Failure)是指当G1无法在堆空间中申请新的分区时,G1便会触发担保机制,执行一次STW式的、单线程的Full GC。Full GC会对整堆做标记清除和压缩,最后将只包含纯粹的存活对象。

    ​ G1在以下场景中会触发Full GC,同时会在日志中记录to-space-exhausted以及Evacuation Failure:

    • 从年轻代分区拷贝存活对象时,无法找到可用的空闲分区
    • 从老年代分区转移存活对象时,无法找到可用的空闲分区
    • 分配巨型对象时在老年代无法找到足够的连续分区

    ​ 由于G1的应用场合往往堆内存都比较大,所以Full GC的收集代价非常昂贵,应该避免Full GC的发生。

    vacuation Failure:

    • 从年轻代分区拷贝存活对象时,无法找到可用的空闲分区
    • 从老年代分区转移存活对象时,无法找到可用的空闲分区
    • 分配巨型对象时在老年代无法找到足够的连续分区

    ​ 由于G1的应用场合往往堆内存都比较大,所以Full GC的收集代价非常昂贵,应该避免Full GC的发生。

    展开全文
  • G1 收集器

    2016-11-17 11:26:16
    1.1 G1收集器通过下面一些方法实现了高性能和减少暂停时间的目的 首先将Java堆空间划分为一些大小相等的区域(region),每个区域都是虚拟机中的一段连续内存空间。G1通过执行并发的全局标记来确定整个Java堆空间中...

    G1是一款面向服务端应用的垃圾收集器。初次发布是在JDK 7这一版本中。长久的目标是替代CMS收集器。

    1.介绍

    1.1 G1收集器通过下面一些方法实现了高性能和减少暂停时间的目的

    首先将Java堆空间划分为一些大小相等的区域(region),每个区域都是虚拟机中的一段连续内存空间。G1通过执行并发的全局标记来确定整个Java堆空间中存活的对象。标记阶段完成后,G1就知道哪些区域基本上是空闲的。在回收内存时优先回收这些区域,这样通常都会回收相当数量的内存。这就是为什么它叫做Garbage-First的原因。顾名思义G1关注某些区域的回收和整理,这些区域中的对象很有可能被完全回收。而且G1使用了一个暂停时间预测模型使得暂停时间控制在用户指定的暂停时间内,并根据用户指定的暂停时间来选择合适的区域回收内存。

    G1确定了可回收的区域后就是筛选回收(evacuation)阶段了。在此阶段将对象从一个或多个区域复制到单一区域,同时整理和释放内存。该阶段是在多个处理器上多个线程并行进行的,因此减少了暂停时间并提高了吞吐量。G1在每一次的垃圾收集过程中都不断地减少碎片,并能够将暂停时间控制在一定范围内。这些已经是以前的垃圾收集器无法完成的了。比如:CMS收集器并不做内存整理。ParallelOld收集器只是对整个Java堆空间做整理,这样导致相当长的暂停时间。

    关于G1很重要的一点是它并不是一个实时收集器。尽管在绝大多数情况下都能够满足暂停时间的要求,但并非没有例外。因为G1是基于之前数次垃圾收集的经验值来估计在用户指定的暂停时间内有多少区域可以收集。因此它对于在区域上执行收集的成本有一个合理的较为精确的模型,并使用该模型来确定对哪些区域执行收集。

    1.2  推荐使用的场景

    G1的首要目的是为那些需要大容量内存和较小GC延迟的应用程序提供解决方案。这通常是指那些堆大小设置在6GB以上,确定的、可以预测的暂停时间在0.5秒以内的应用程序。
    如果应用程序符合以下一项或者多项特征,那么从CMS或者ParallelOld收集器切换到G1可能更合适。
    活动对象占据了超过50%的Java堆空间。
    对象分配率或者提升率波动明显。
    不希望有长时间的垃圾收集暂停时间(超过0.5秒或1秒)。

    1.3 G1的前景

    G1的使命是替换掉CMS收集器。通过对比G1和CMS收集器,可以发现G1是更好的一种解决方案。首先G1是一个压缩收集器,G1通过充分的压缩完全避免了使用细粒度的空闲列表(free lists)来分配内存,而是使用相对粗粒度的区域(regions)来分配内存。这明显简化了收集器,也很大程度上减少了内存碎片化的问题。此外,相比较CMS,G1可以预测出垃圾收集的暂停时间,并允许用户指定期望的暂停时间。

    2.参数

    它既能管理新生代,也能管理老年代,所以不需要和其他收集器搭配。
    -XX:+UseG1GC   //指定使用G1收集器
    -XX:MaxGCPauseMillis=300   //期望一次回收暂停时间不要超过300毫秒

    3.日志格式


    OpenJDK 64-Bit Server VM (25.66-b60) for linux-amd64 JRE (1.8.0_66-b60), built on Dec  2 2015 09:54:46 by "admin" with gcc 4.4.7
    Memory: 4k page, physical 8388608k(5097132k free), swap 1999864k(1999864k free)
    CommandLine flags: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/admin/logs/java.hprof -XX:InitialHeapSize=4294967296 -XX:MaxGCPauseMillis=300 -XX:MaxHeapSize=4294967296 -XX:MaxMetaspaceSize=402653184 -XX:MaxNewSize=2147483648 -XX:NewSize=2147483648 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC 
    2016-11-17T11:11:10.789+0800: 3.552: [GC pause (Metadata GC Threshold) (young) (initial-mark), 0.1077120 secs]
       [Parallel Time: 39.1 ms, GC Workers: 4]
          [GC Worker Start (ms): Min: 3552.8, Avg: 3552.8, Max: 3552.8, Diff: 0.0]
          [Ext Root Scanning (ms): Min: 1.4, Avg: 1.6, Max: 2.0, Diff: 0.5, Sum: 6.3]
          [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
             [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
          [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
          [Code Root Scanning (ms): Min: 0.5, Avg: 0.8, Max: 1.2, Diff: 0.6, Sum: 3.1]
          [Object Copy (ms): Min: 36.3, Avg: 36.5, Max: 36.9, Diff: 0.6, Sum: 146.1]
          [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
             [Termination Attempts: Min: 1, Avg: 2.0, Max: 3, Diff: 2, Sum: 8]
          [GC Worker Other (ms): Min: 0.0, Avg: 0.1, Max: 0.1, Diff: 0.0, Sum: 0.2]
          [GC Worker Total (ms): Min: 38.9, Avg: 39.0, Max: 39.0, Diff: 0.1, Sum: 155.8]
          [GC Worker End (ms): Min: 3591.7, Avg: 3591.7, Max: 3591.8, Diff: 0.0]
       [Code Root Fixup: 0.6 ms]
       [Code Root Purge: 0.1 ms]
       [Clear CT: 0.1 ms]
       [Other: 67.8 ms]
          [Choose CSet: 0.0 ms]
          [Ref Proc: 66.5 ms]
          [Ref Enq: 0.1 ms]
          [Redirty Cards: 0.1 ms]
          [Humongous Register: 0.0 ms]
          [Humongous Reclaim: 0.0 ms]
          [Free CSet: 0.4 ms]
       [Eden: 328.0M(2048.0M)->0.0B(1982.0M) Survivors: 0.0B->66.0M Heap: 328.0M(4096.0M)->64.6M(4096.0M)]
     [Times: user=0.18 sys=0.04, real=0.11 secs] 
    2016-11-17T11:11:10.898+0800: 3.661: [GC concurrent-root-region-scan-start]
    2016-11-17T11:11:10.958+0800: 3.721: [GC concurrent-root-region-scan-end, 0.0602273 secs]
    2016-11-17T11:11:10.958+0800: 3.721: [GC concurrent-mark-start]
    2016-11-17T11:11:10.958+0800: 3.721: [GC concurrent-mark-end, 0.0006063 secs]
    2016-11-17T11:11:10.959+0800: 3.722: [GC remark 2016-11-17T11:11:10.959+0800: 3.722: [Finalize Marking, 0.0003445 secs] 2016-11-17T11:11:10.959+0800: 3.722: [GC ref-proc, 0.0000522 secs] 2016-11-17T11:11:10.959+0800: 3.722: [Unloading, 0.0050686 secs], 0.0057804 secs]
     [Times: user=0.01 sys=0.00, real=0.00 secs] 
    2016-11-17T11:11:10.964+0800: 3.728: [GC cleanup 78M->78M(4096M), 0.0035612 secs]
     [Times: user=0.01 sys=0.00, real=0.01 secs] 
    2016-11-17T11:11:13.361+0800: 6.124: [GC pause (Metadata GC Threshold) (young) (initial-mark), 0.1394786 secs]
       [Parallel Time: 51.8 ms, GC Workers: 4]
          [GC Worker Start (ms): Min: 6124.5, Avg: 6124.6, Max: 6124.8, Diff: 0.3]
          [Ext Root Scanning (ms): Min: 2.4, Avg: 3.2, Max: 4.4, Diff: 1.9, Sum: 12.7]
          [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
             [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
          [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.1]
          [Code Root Scanning (ms): Min: 0.0, Avg: 0.6, Max: 2.5, Diff: 2.5, Sum: 2.6]
          [Object Copy (ms): Min: 46.5, Avg: 47.6, Max: 48.7, Diff: 2.1, Sum: 190.6]
          [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 0.4]
             [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 4]
          [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
          [GC Worker Total (ms): Min: 51.4, Avg: 51.6, Max: 51.7, Diff: 0.3, Sum: 206.6]
          [GC Worker End (ms): Min: 6176.2, Avg: 6176.2, Max: 6176.3, Diff: 0.0]
       [Code Root Fixup: 0.8 ms]
       [Code Root Purge: 0.0 ms]
       [Clear CT: 0.3 ms]
       [Other: 86.6 ms]
          [Choose CSet: 0.0 ms]
          [Ref Proc: 85.4 ms]
          [Ref Enq: 0.1 ms]
          [Redirty Cards: 0.1 ms]
          [Humongous Register: 0.0 ms]
          [Humongous Reclaim: 0.0 ms]
          [Free CSet: 0.5 ms]
       [Eden: 508.0M(1982.0M)->0.0B(1974.0M) Survivors: 66.0M->74.0M Heap: 571.6M(4096.0M)->73.0M(4096.0M)]
     [Times: user=0.29 sys=0.05, real=0.14 secs] 
    2016-11-17T11:11:13.501+0800: 6.264: [GC concurrent-root-region-scan-start]
    2016-11-17T11:11:13.569+0800: 6.332: [GC concurrent-root-region-scan-end, 0.0679650 secs]
    2016-11-17T11:11:13.569+0800: 6.332: [GC concurrent-mark-start]
    2016-11-17T11:11:13.570+0800: 6.333: [GC concurrent-mark-end, 0.0006412 secs]
    2016-11-17T11:11:13.570+0800: 6.333: [GC remark 2016-11-17T11:11:13.570+0800: 6.333: [Finalize Marking, 0.0003852 secs] 2016-11-17T11:11:13.570+0800: 6.334: [GC ref-proc, 0.0000721 secs] 2016-11-17T11:11:13.570+0800: 6.334: [Unloading, 0.0060320 secs], 0.0068158 secs]
     [Times: user=0.02 sys=0.00, real=0.01 secs] 
    2016-11-17T11:11:13.577+0800: 6.340: [GC cleanup 76M->76M(4096M), 0.0041485 secs]
     [Times: user=0.01 sys=0.00, real=0.00 secs] 


    展开全文
  • g1收集器

    2020-03-26 16:52:18
    https://blog.csdn.net/coderlius/article/details/79272773
    展开全文
  • JVM进阶(十一)——JAVA G1收集器

    万次阅读 2017-03-13 10:34:40
    JVM进阶(十一)——JAVA G1收集器  在前两篇博文中讲解了新生代和年老代的收集器,在本篇博文中介绍一个收集范围涵盖整个堆的收集器——G1收集器。 先讲讲G1收集器的特点,他也是个多线程的收集器,能够充分利用多...

    #JVM进阶(十一)——JAVA G1收集器
      在前两篇博文中讲解了新生代和年老代的收集器,在本篇博文中介绍一个收集范围涵盖整个堆的收集器——G1收集器。
    先讲讲G1收集器的特点,他也是个多线程的收集器,能够充分利用多个CPU进行工作,收集方式也与CMS收集器类似,因此不会有太久的停顿。
      虽然回收的范围是整个堆,但还是有分代回收的回收方式。在年轻代依然采用复制算法;年老代也同样采用“标记-清除-整理”算法。但是,新生代与老年代在堆内存中的布局就和以往的收集器有着很大的区别:G1将整个堆分成了一个个大小相等的独立区域,叫做region。其中依然保存着新生代和年老代的概念,如图:
    这里写图片描述
      是不是和之前博文中看到的不同(这是内存空间图,不要和垃圾回收的图弄混了),以往只是简单的分区域,而这里是将整个堆分成多个大小相等的区域。
      他的回收过程也分为四个部分:初始标记、并发标记、最终标记、筛选回收。
      大家是不是觉得很熟悉!上面我们也说过了,和CMS收集器类似,初始标记需要STW;并发标记不需要;最终标记就是做一些小修改,需要STW;而筛选回收则有些不同,在众多的region中,每个region可回收的空间各不相同,但是回收所消耗的时间是需要控制的,不能太长,因此G1就会筛选出一些可回收空间比较大的region进行回收,这就是G1的优先回收机制。这也是保证了G1收集器能在有限的时间内能够获得最高回收效率的原因。通过-XX:MaxGCPauseMills=50毫秒设置有限的收集时间。
      每个region之间的对象引用通过remembered set来维护,每个region都有一个remembered set,remembered set中包含了引用当前region中对象的指针。虚拟机正是通过这个remembered set去避免对整个堆进行扫描来确认可回收的对象。
      到此,所有的收集器都已经讲完了,但是很重要的一点:每个收集器是不能随意进行组合使用的!这里我列出一个搭配使用的表格提供大家参考使用:
    这里写图片描述

    ![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTYxMjIwMjEwNjM2NzA1?x-oss-process=image/format,png) ![这里写图片描述](https://imgconvert.csdnimg.cn/aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTYxMjIwMjEwNzMzNDQ2?x-oss-process=image/format,png)
    展开全文
  • G1收集器和CMS收集器

    2020-12-14 15:39:40
    G1收集器 G1(Garbage-First)收集器是当今收集器技术发展最前沿的成果之一,它是一款面向服务端应用的垃圾收集器,HotSpot开发团队赋予它的使命是(在比较长期的)未来可以替换掉JDK 1.5中发布的CMS收集器。与其他...
  • G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用。 区别二:使用的算法不一样 CMS收集器是使用“标记-清除”算法进行的垃圾回收。 G1收集器使用的是“标记-整理”算法进行的垃圾回收。 区别三:CMS收集...
  • 关于CMS收集器与G1收集器CMS收集器介绍G1收集器 写这篇文章也是源于前几天阿里一面时被问到“CMS收集器有哪些措施让它比其他收集器更优秀时”回答不上来,文章参考《深入理解JAVA虚拟机》 CMS收集器介绍 CMS...
  • 垃圾收集器之:G1收集器 G1垃圾收集器是一种工作在堆内不同分区上的并发收集器。分区既可以归属于老年代,也可以归属新生代,同一个代的分区不需要保持连续。为老年代设计分区的初衷是我们发现并发后台线程在回收老...
  • G1收集器是当前收集器技术发展的最前沿成果,在JDK1.6_Updata14中提供了Early Access版本的G1收集器以供适用。G1收集器是垃圾收集器理论进一步发展的产物,它与前面的CMS收集器相比有两个显著的改进:一是G收集器是...
  • G1回收器的特点优势缺点G1收集器的运作过程G1参数设置G1回收器的常见操作步骤G1回收器的适用场景Region的使用介绍设置H的原因Reference 简介 官方给G1设定的目标是:在延迟可控的情况下获得尽可能高的吞吐量,开创...
  • G1收集器G1收集器是面向服务端应用的垃圾收集器。G1收集器在未来可能替换掉CMS收集器。G1收集器的特点: 并行与并发:G1能充分利用多CPU、多核环境下的硬件优势、使用多个CPU来缩短stop the world 停顿时间,部分...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,556
精华内容 1,022
关键字:

g1收集器