天天看点

架构师必备,如何优化垃圾回收机制

作者:诗歌乐园

如果要对GC调优,必须掌握垃圾回收机制的基础知识,比如说JVM的内存模型,垃圾回收机制等。

这里我们重点讲下七种垃圾回收器

一.七种垃圾回收器

1.串型垃圾回收器:Serial,Serial Old

2.并行垃圾回收器:ParNew,Parallel Scavenge,Parallel Old

3.并发垃圾回收器:CMS,G1

1.新生代垃圾回收器:Serial,ParNew,Parallel Scavenge

2.老年代垃圾回收器:Serial Old,Parallel Old,CMS

3.整堆收集器:G1

二.七种垃圾回收器的特点

1.Serial垃圾回收器,单线程,简单高效,使用复制算法。回收时会暂停工作线程,业务处理会出现停顿。

2.Serial Old回收器同样也采用了串行回收"Stop the World"机制,只不过内存回收算法使用的是标记-整理算法

3.ParNew回收器本质上是Serial的多线程版本,使用复制算法,只有他能和CMS配合使用。

4.Parallel Scavenge回收器,JDK8默认的新生代垃圾回收器,使用需求为高吞吐量时使用该收集器,采用“复制算法”。

5.Parallel Old回收器,是Parallel Scavenge的老年代版本,采用标记--整理算法。

6.CMS回收器,工作在老年代,即Concurrent Mark Sweep收集器,追求最短的停顿时间,采用标记清除算法。CMS回收分为初始预标记(STW),并发标记,并发预清理,重新标记(STW),并发清除。

7.G1回收器,全代回收器,可以设置STW的时间,将整个堆分为内存大小相等的区域(Region),每个区域有一个称为回收价值的属性,G1通过该属性判断是否进行垃圾回收,从而达到最高垃圾回收效率。它依旧保留了新生代和老年代的概念,老年代和新生代的物理空间不再是连续的,它们都是region的集合。

G1将所有Region分为四种类型:Eden、Survivor、Old、Humongous。

架构师必备,如何优化垃圾回收机制

默认新生代的Region内存占堆空间的5%,如果堆空间大小为4096MB,那么新生代占用200MB左右的内存,按照每个Region为2MB,对应就是100个Region。也可以通过参数-XX:G1NewSizePercent设置新生代初始占比。

在系统运行过程中,JVM会动态地给年轻代增加更多的Region,但新生代的占比最多不会超过60%,可以通过参数-XX:G1MaxNewSizePercent设置。Region的区域类型是动态变化的,可能之前是年轻代,经过了垃圾回收之后就变成了老年代。

G1中的新生代依然与经典垃圾收集器中一样,分为Eden区和Survivor区,默认比例也是8:1:1,如果新生代有100个Region,那么就是Eden区占用80个,两个Survivor区各占用10个。

G1收集器对于对象从新生代转移到老年代与CMS等经典垃圾收集器是一样的,但对于大对象的处理有所不同。G1为大对象的内存分配专门设计了一个Humongous类型的Region,而不再是让对象直接进入老年代的Region。

在G1中,大对象的判断是超过一个Region大小的50%,按照每个Region大小为2MB来计算,只要对象超过了1MB,就会被放入到Humongous的Region中,如果一个对象太大,一个Region放不下,可能会存在跨多个Region来存放。

在进行Full GC的时候除了要收集新生代和老年代的Region外,还会将Humongous的Region一并进行回收。

与之前的经典垃圾收集器不同,G1可以由用户自己去设置STW的最大时间,然后G1会根据STW的时间来进行内存回收,这个STW的时间包含了并发标记、最终标记和筛选回收三个阶段STW的总时间。

三.如何判断是否需要GC优化

如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化,如果GC时间超过1-3秒,或者频繁GC,则必须优化。

注:如果满足下面的指标,则一般不需要进行GC:

Minor GC执行时间不到50ms;

Minor GC执行不频繁,约10秒一次;

Full GC执行时间不到1s;

Full GC执行频率不算频繁,不低于10分钟1次;

四.如何对gc调优

1.降低Minor GC频率

通常情况下,由于新生代空间较小,Eden区很快被填满,造成频繁的Minor GC,因此我们需要增大新生代的空间来降低Minor GC。

2.降低Full GC的频率

堆内存不足或老年代对象太多,会触发full gc,频繁的full gc会带来上下文切换,增加系统的性能开销。可以使用哪些方法来降低full gc的频率呢?

2.1.减少创建大对象

2.2.增大堆内存空间

3.选择合适的gc回收器

当我们对响应时间有要求时,我们可以选择相应速度快的垃圾回收器,CMS回收器和G1回收器都是不错的选择。

如果我们对系统吞吐量有要求时,可以选择Parallel Scavenge回收器来提高系统吞吐量。

继续阅读