wordpress 上传 pdf,上海优化外包公司排名,西安旅游攻略2天自由行攻略,阜宁网站制作选哪家G1收集器(-XX:UseG1GC)
前置文章#xff1a;JVM垃圾收集器
G1 (Garbage-First)是一款面向服务器的垃圾收集器#xff0c;主要针对配备多颗处理器及大容量内存的机器。以极高概率满足GC停顿时间要求的同时#xff0c;还具备高吞吐量性能特征。 G1将Java堆划分为多个大小相等…G1收集器(-XX:UseG1GC)
前置文章JVM垃圾收集器
G1 (Garbage-First)是一款面向服务器的垃圾收集器主要针对配备多颗处理器及大容量内存的机器。以极高概率满足GC停顿时间要求的同时还具备高吞吐量性能特征。 G1将Java堆划分为多个大小相等的独立区域RegionJVM目标是不超过2048个Region(JVM源码里TARGET_REGION_NUMBER定义)实际可以超过该值但是不推荐。一般Region大小等于堆大小除以2048比如堆大小为4096M则Region大小为2M当然也可以用参数-XX:G1HeapRegionSize手动指定Region大小但是推荐默认的计算方式。G1保留了年轻代和老年代的概念但不再是物理隔阂了它们都是可以不连续Region的集合。
默认年轻代对堆内存的占比是5%如果堆大小为4096M那么年轻代占据200MB左右的内存对应大概是100个Region可以通过-XX:G1NewSizePercent设置新生代初始占比在系统运行中JVM会不停的给年轻代增加更多的Region但是最多新生代的占比不会超过60%可以通过-XX:G1MaxNewSizePercent调整。年轻代中的Eden和Survivor对应的region也跟之前一样默认8:1:1假设年轻代现在有1000个regioneden区对应800个s0对应100个s1对应100个。
一个Region可能之前是年轻代如果Region进行了垃圾回收之后可能又会变成老年代也就是说Region的区域功能可能会动态变化。
G1垃圾收集器对于对象什么时候会转移到老年代跟之前讲过的原则一样唯一不同的是对大对象的处理G1有专门分配大对象的Region叫Humongous区而不是让大对象直接进入老年代的Region中。在G1中大对象的判定规则就是一个大对象超过了一个Region大小的50%比如按照上面算的每个Region是2M只要一个大对象超过了1M就会被放入Humongous中而且一个大对象如果太大可能会横跨多个Region来存放。
Humongous区专门存放短期巨型对象不用直接进老年代可以节约老年代的空间避免因为老年代空间不够的GC开销。Full GC的时候除了收集年轻代和老年代之外也会将Humongous区一并回收。
G1收集器一次GC(主要值Mixed GC)的运作过程大致分为以下几个步骤
初始标记initial markSTW 暂停所有的其他线程并记录下gc roots直接能引用的对象速度很快 并发标记Concurrent Marking 同CMS的并发标记最终标记RemarkSTW 同CMS的重新标记筛选回收CleanupSTW 筛选回收阶段首先对各个Region的回收价值和成本进行排序根据用户所期望的GC停顿STW时间(可以用JVM参数-XX:MaxGCPauseMillis指定)来制定回收计划比如说老年代此时有1000个Region都满了但是因为根据预期停顿时间本次垃圾回收可能只能停顿200毫秒那么通过之前回收成本计算得知可能回收其中800个Region刚好需要200ms那么就只会回收800个Region(Collection Set要回收的集合)尽量把GC导致的停顿时间控制在我们指定的范围内。这个阶段其实也可以做到与用户程序一起并发执行但是因为只回收一部分Region时间是用户可控制的而且停顿用户线程将大幅提高收集效率。不管是年轻代或是老年代回收算法主要用的是复制算法将一个region中的存活对象复制到另一个region中这种不会像CMS那样回收完因为有很多内存碎片还需要整理一次G1采用复制算法回收几乎不会有太多内存碎片。(注意CMS回收阶段是跟用户线程一起并发执行的G1因为内部实现太复杂暂时没实现并发回收不过到了ZGCShenandoah就实现了并发收集Shenandoah可以看成是G1的升级版本) G1收集器在后台维护了一个优先列表每次根据允许的收集时间优先选择回收价值最大的Region(这也就是它的名字Garbage-First的由来)比如一个Region花200ms能回收10M垃圾另外一个Region花50ms能回收20M垃圾在回收时间有限情况下G1当然会优先选择后面这个Region回收。这种使用Region划分内存空间以及有优先级的区域回收方式保证了G1收集器在有限时间内可以尽可能高的收集效率。
被视为JDK1.7以上版本Java虚拟机的一个重要进化特征。它具备以下特点
并行与并发 G1能充分利用CPU、多核环境下的硬件优势使用多个CPUCPU或者CPU核心来缩短Stop-The-World时间。部分其他收集器原本需要停顿Java线程来执行GC动作G1收集器仍然可以通过并发的方式让java程序继续执行。分代收集 虽然G1可以不需要其他收集器配合就能独立管理整个GC堆但是还是保留了分代的概念。可预测的停顿 这是G1相对于CMS的另一个大优势降低停顿时间是G1 和 CMS 共同的关注点但G1 除了追求低停顿外还能建立可预测的停顿时间模型能让使用者明确指定在一个长度为M毫秒的时间片段(通过参数-XX:MaxGCPauseMillis指定)内完成垃圾收集。
毫无疑问 可以由用户指定期望的停顿时间是G1收集器很强大的一个功能 设置不同的期望停顿时间 可使得G1在不同应用场景中取得关注吞吐量和关注延迟之间的最佳平衡。 不过 这里设置的“期望值”必须是符合实际的 不能异想天开 毕竟G1是要冻结用户线程来复制对象的 这个停顿时间再怎么低也得有个限度。 它默认的停顿目标为两百毫秒 一般来说 回收阶段占到几十到一百甚至接近两百毫秒都很正常 但如果我们把停顿时间调得非常低 譬如设置为二十毫秒 很可能出现的结果就是由于停顿目标时间太短 导致每次选出来的回收集只占堆内存很小的一部分 收集器收集的速度逐渐跟不上分配器分配的速度 导致垃圾慢慢堆积。 很可能一开始收集器还能从空闲的堆内存中获得一些喘息的时间 但应用运行时间一长就不行了 最终占满堆引发Full GC反而降低性能 所以通常把期望停顿时间设置为一两百毫秒或者两三百毫秒会是比较合理的。
YoungGC
YoungGC并不是说现有的Eden区放满了就会马上触发G1会计算下现在Eden区回收大概要多久时间如果回收时间远远小于参数 -XX:MaxGCPauseMills 设定的值那么增加年轻代的region继续给新对象存放不会马上做Young GC直到下一次Eden区放满G1计算回收时间接近参数 -XX:MaxGCPauseMills 设定的值那么就会触发Young GC
MixedGC
老年代的堆占有率达到参数(-XX:InitiatingHeapOccupancyPercent)设定的值则触发回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)以及大对象区正常情况G1的垃圾收集是先做MixedGC主要使用复制算法需要把各个region中存活的对象拷贝到别的region里去拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC
Full GC
停止系统程序然后采用单线程进行标记、清理和压缩整理好空闲出来一批Region来供下一次MixedGC使用这个过程是非常耗时的。(Shenandoah优化成多线程收集了)
G1收集器参数设置
-XX:UseG1GC 使用G1收集器-XX:ParallelGCThreads 指定GC工作的线程数量-XX:G1HeapRegionSize 指定分区大小(1MB~32MB且必须是2的N次幂)默认将整堆划分为2048个分区-XX:MaxGCPauseMillis 目标暂停时间(默认200ms)-XX:G1NewSizePercent 新生代内存初始空间(默认整堆5%值配置整数默认就是百分比)-XX:G1MaxNewSizePercent 新生代内存最大空间-XX:TargetSurvivorRatio Survivor区的填充容量(默认50%)Survivor区域里的一批对象(年龄1年龄2年龄n的多个年龄对象)总和超过了Survivor区域的50%此时就会把年龄n(含)以上的对象都放入老年代-XX:MaxTenuringThreshold 最大年龄阈值(默认15)-XX:InitiatingHeapOccupancyPercent 老年代占用空间达到整堆内存阈值(默认45%)则执行新生代和老年代的混合收集(MixedGC)比如我们之前说的堆默认有2048个region如果有接近1000个region都是老年代的region则可能就要触发MixedGC了-XX:G1MixedGCLiveThresholdPercent(默认85%) region中的存活对象低于这个值时才会回收该region如果超过这个值存活对象过多回收的的意义不大。-XX:G1MixedGCCountTarget 在一次回收过程中指定做几次筛选回收(默认8次)在最后一个筛选回收阶段可以回收一会然后暂停回收恢复系统运行一会再开始回收这样可以让系统不至于单次停顿时间过长。-XX:G1HeapWastePercent(默认5%) gc过程中空出来的region是否充足阈值在混合回收的时候对Region回收都是基于复制算法进行的都是把要回收的Region里的存活对象放入其他Region然后这个Region中的垃圾对象全部清理掉这样的话在回收过程就会不断空出来新的Region一旦空闲出来的Region数量达到了堆内存的5%此时就会立即停止混合回收意味着本次混合回收就结束了。
G1垃圾收集器优化建议
假设参数 -XX:MaxGCPauseMills 设置的值很大导致系统运行很久才会做年轻代gc年轻代可能都占用了堆内存的60%了此时才触发年轻代gc。那么存活下来的对象可能就会很多此时就会导致Survivor区域放不下那么多的对象就会进入老年代中。或者是你年轻代gc过后存活下来的对象过多导致进入Survivor区域后触发了动态年龄判定规则达到了Survivor区域的50%也会快速导致一些对象进入老年代中。所以这里核心还是在于调节 -XX:MaxGCPauseMills 这个参数的值在保证他的年轻代gc别太频繁的同时还得考虑每次gc过后的存活对象有多少避免存活对象太多快速进入老年代频繁触发mixed gc。