码迷,mamicode.com
首页 > 其他好文 > 详细

JVM垃圾回收器、内存分配与回收策略

时间:2020-12-01 11:55:56      阅读:4      评论:0      收藏:0      [点我收藏+]

标签:cpu   卡顿   gid   col   com   多线程   技术   生命周期   版本   

新生代垃圾收集器

1. Serial收集器

serial收集器即串行收集器,是一个单线程收集器。

串行收集器在进行垃圾回收时只使用一个CPU或一条收集线程去完成垃圾回收工作,并且会暂停其他的工作线程(stop the world),直至回收完成。适用于运行在client模式下的JVM。

在单CPU年代,串行收集器是默认的垃圾回收器,minor GC和major GC的过程都是用一个线程去处理的。

启用方式:-XX: +UseSerialGC

2. ParNew收集器

parNew收集器即并行收集器,采用的是多线程方式进行垃圾回收,可以理解为Serial收集器的多线程版本,吞吐量要比串行高很多,是服务器级别的虚拟机默认使用的,用来处理新生代的垃圾回收器。

因为采用的是并行多线程方式,建议在多CPU环境下使用,否则和Serial没有区别。

启用方式:-XX: +UseParNewGC

3. Parallel Scavenge收集器

并行的多线程垃圾收集器,采用复制算法进行垃圾回收,非常适合服务器做计算任务时使用。

一般的垃圾回收器是在尽量短的时间内进行垃圾回收,这样程序与用户交互的时间间隔比较小,不会出现长时间的卡顿现象。但是Parallel Scavenge更侧重于系统的吞吐量,高效的利用CPU,优先处理计算任务,适合交互少、运算多的场景。

通过参数-XX: MaxGcPauseMills设置GC最大停顿时间,通过参数-XX: GCTimeRatio设置吞吐量大小。

启用方式:-XX: +UseParallelGC

老年代垃圾收集器

1. Serial Old收集器

serial收集器的老年代版本,同样是单线程收集器、stop the world,使用标记整理算法。一般启用方式:UseSerialGC是Serial + Serial OldUseParNewGC是ParNew + Serial OldUseParallelGC是Parallel Scavenge + Serial Old

2. Parallel Old收集器

老年代版本的Parallel Scavenge,使用多线程 + 标记整理算法。启用方式:-XX: +UseParallelOldGC

3. CMS垃圾收集器

CMS收集器的主要目的是使垃圾回收造成的停顿时间最短,提高服务响应速度,使用标记清除算法,具有并发收集(用户线程与垃圾收集并发执行)、低停顿的特点。运行过程分为以下四个步骤:

1. 初始标记:stop the world,只是标记一下GC Roots能直接关联到的对象,速度快

2. 并发标记:进行GC RootsTracing过程

3. 重新标记:stop the world,修正并发标记期间因用户程序继续运行而导致的标记产生变动的那部分对象的标记记录。这个阶段停顿时间相对初始标记时间长,比并发标记时间短

4. 并发清除注意:

  1. CMS收集器对CPU资源敏感,这是面向并发程序设计的共性
  2. 无法处理浮动垃圾(CMS垃圾收集阶段,用户线程仍在运行,因此会有新的垃圾生成,这部分垃圾只能在下一次GC时再清理,即浮动垃圾),可能出现"Concurrent Mode Failure"失败导致另一次full GC

启用方式:-XX:+UseConcMarkSweepGC

G1收集器

G1收集器是基于标记整理算法实现的收集器,所以它不会产生内存空间碎片,并且可以精确的控制停顿时间。能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。

G1的设计原则就是简单可行的性能调优,只需声明以下参数即可:
-XX:+UseG1GC -Xmx16g -XX:MaxGCPauseMills=300

其中,-XX:+UseG1GC表明开启G1收集器,-Xmx16g设置堆内存为16g,-XX:MaxGCPauseMills=300设置GC停顿最大时间为300ms。如果我们需要调优,在内存一定的情况下,可以考虑修改该参数,当然还要根据实际业务场景来处理。

G1取消了堆内结构的新生代、老年代的物理空间划分,将整个Java堆划分为大小固定的独立区域,后台维护一个优先列表来跟踪这些区域的垃圾堆积程度,每次根据允许收集的时间,优先回收垃圾最多的区域。

G1中的Humongous区域用于存储生命周期较短的巨型对象(一个对象所占空间超过了分区容量的50%),如果一个Humongous区无法装下一个巨型对象,G1会寻找连续的H分区来存储,如果没有连续的H区满足这种情况,有时候会触发full GC。

G1收集器的运作主要划分为以下四个步骤:

  1. 初始标记:标记GC Roots能直接关联到的对象,需要停顿线程,但耗时很短
  2. 并发标记:从GC Roots开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行
  3. 最终标记:修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录
  4. 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划

内存分配与回收策略

对象的内存分配主要是指在Java堆上的分配,通常会优先分配在新生代,然后经历一系列GC后仍然存活的对象会进入到老年代。少数情况下,一些对象也会直接进入到老年代。

-Xms:设置初始化堆内存,-Xmx设置最大堆内存,设置为相等可防止内存抖动(剩余内存大于70%、小于40%时,自动触发内存扩大或缩小)

1. 对象会优先分配在新生代

新生代划分为一个eden区和两个survivor区(from survivor、to survivor)。初始阶段,新创建的对象会分配给eden区。新生代发生的GC成为minor GC即Young GC,主要分为以下几个过程:

  1. 随着eden区存储的对象不断增多,当eden区剩余空间无法存储新生成的对象时会触发GC
  2. 经过minor GC后仍然存活的对象会进入from survivor区
  3. 当再次触发GC时,会扫描eden区和from survivor区,对这两个区域进行垃圾回收,仍然存活的对象会被复制到to survivor区,同时这些存活的对象年龄加1
  4. 清空eden、from survivor区中的对象,并将from survivor和to survivor区互换
  5. 频繁执行上述过程,当剩余存活对象年龄达到15(默认)时,这些对象会进入老年代,通过参数-XX:MaxTenuringThreshold控制

-Xmn用来设置新生代大小,一般设置为整个堆内存的3/1或者1/4

-XX:NewRatio设置新生代与老年代的堆内存比例

-XX:SurvivorRatio设置eden区和survivor区之间的比例

2. 老年代存储的对象

发生在老年代的GC是major GC,回收速度会比minor GC慢。

上文已经说明了对象进入老年代的一种情况即长期存活的对象会进入老年代,这里再来看看其他情况:

1. 大对象直接进入老年代大对象需要的连续存储空间(如数组)大于新生代剩余空间时,会直接进入老年代。

通过参数-XX:PretenureSizeThreshold设置,大于该参数值的对象会直接进入老年代(避免新生代中大量对象的拷贝,效率低)

注意:PretenureSizeThreshold参数只对部分垃圾回收器有效,比如Serial和ParNew

2. 如果survivor区相同年龄所有对象大小的总和大于survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,无需等到MaxTenuringThreshold设置的年龄

注意:永久代不属于堆空间,通过参数-XX:PermSize,-XX:MaxPermSize控制大小

3. Full GC

full GC是针对整个Java堆空间进行垃圾回收,包括新生代和老年代,会造成stop world。要尽量避免full GC,它会影响程序的稳定性。

导致Full GC的几点原因:

1. 老年代空间不足从年轻代进入老年代的对象所占空间大于老年代剩余空间大小。eden区调大一些,尽量让对象在新生代minor GC回收,而不是集中在老年代进行major GC,尽量不要创建特别大的对象

2. 垃圾回收算法用的不对比如在老年代使用复制收集算法

3. 永久代空间不足

4. 被HandlePromotionFailure参数强制Full GC

在发生minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则改为进行full GC。如果小于,则根据HandlePromotionFailure的设置是否允许担保分配内存失败:如果允许失败,则只进行minor GC;反之,则进行full GC。

但是如果发生HandlePromotionFailure失败,则会进行full GC。


 

关注微信公众号:大数据学习与分享,获取更对技术干货

JVM垃圾回收器、内存分配与回收策略

标签:cpu   卡顿   gid   col   com   多线程   技术   生命周期   版本   

原文地址:https://www.cnblogs.com/bigdatalearnshare/p/14015094.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!