垃圾收集器

Posted javatww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了垃圾收集器相关的知识,希望对你有一定的参考价值。

1.      并发与并行

1)       并发:多条垃圾收集器线程并行工作,用户线程处于等待状态

2)       并行:用户线程和垃圾收集线程同时执行(不一定并行,可能会交替执行)

2.      Serial收集器(新生代,单线程,复制算法收集器,最基本,最悠久的收集器,JDK1.3.1版本之前)

1)       单线程收集器:不表示只使用一个cpu或一条收集线程完成垃圾收集,而是在垃圾收集时必需暂停其他所有工作线程,直到收集结束

2)       用户体验恶劣

3)       Client模式下默认新生代收集器(几十到一两百兆控制在几十到一百多毫秒)

4)       没有线程交互的开销,简单且高效

3.      ParNew收集器(新生代,多线程,复制算法收集器)

1)       可以看成Serial收集器的多线程版本

2)       许多运行在Server模式的虚拟机的首选新生代收集器(因为可以和CMS老年代收集器配合使用)

3)       +UseConcMarkSweepGC选项的默认收集器,+UseParNewGC强制指定

4)       性能并不一定比Serial收集器高

5)       默认开启垃圾收集线程数与CPU数量相同(ParallelGCThreads参数指定)

4.      Parallel Scavenge收集器(新生代,多线程,复制算法收集器)

1)       目标:达到可控吞吐量(CPU运行用户代码时间和CPU总耗时比例),高效使用CPU

2)       适合后台运算而不需要太多交互的

3)       MaxGCPauseMillis最大垃圾收集停顿时间,一个大于0 的毫秒数

4)       GCTimeRatio吞吐量大小,0-100(不包含)范围内的整数,设置19就表示1/1+19)即5%

5)       +UseAdaptiveSizePolicyGC自适应条件策略开关,根据性能监控信息动态设置参数以提供最合适的停顿时间和最大吞吐量

5.      Serial Old收集器(老年代,单线程,标记-整理算法收集器)

1)       主要被Client模式下虚拟机使用

2)       Server模式下使用

a          Jdk1.5之前和Parallel Scavenge收集器搭配使用

b        作为CMS收集器的后备预案(失败的时候使用)

6.      Parallel Old收集器(老年代,多线程,标记-整理算法收集器)

a          Parallel Scavenge收集器搭配,适合注重吞吐量和CPU资源的场合

7.      CMS收集器(老年代,多线程,标记-清除算法收集器)

Concurrent Mark Sweep,以最短回收停顿时间为目标,符合互联网B/S系统需求,用户体验较好,过程步骤如下

a          初始标记:标记GCRoots能直接关联的对象,需要暂停其他工作线程,耗时最短

b        并发标记:进行GCRoots Tracing过程

c             重新标记:修正并发标记期间,因用户程序运作产生变动对象的标记记录,需要暂停其他工作线程,比初始标记时间长点

d        并发清除:

1)       并发标记和并发清除耗时最长,所以可以视为CMS收集器和用户线程一起并发执行

2)       低停顿

3)       缺点如下:

a          CPU资源非常敏感,会导致用户线程变慢,总吞吐量降低,CMS默认开启线程数(CPU数量+3/4,当CPU数量大于4时,占用不超过25%,当不足4个,影响会很大

b        增量式并发收集器(i-CMS):让GC线程和用户线程交替运行,垃圾处理时间更长,但对用户程序影响减少,但此方法已被声明为不提倡使用

c             CMS无法处理浮动垃圾(浮动垃圾:出现在标记之后,程序运行产生的,CMS本次无法处理的垃圾),可能出现处理失败(Concurrent Mode Failure)的情况,进而导致另一次Full FC

d        由于并发,老年代需要预留部分空间给收集时的程序使用,默认情况下老年代使用68%就会被激活。若老年代增长不快可以通过CMSInitiatingOccupancyFraction来适当调高,以降低回收次数;若此参数设置太高不能满足程序运行需要会产生大量Concurrent Mode Failure,虚拟机会临时启动Serial Old收集器,因此停顿会变长,性能因此降低

e            因为使用标记-清除算法会产生大量碎片。使用+UseCMSCompactAtFullCollection参数,在Full GC后进行碎片整理,但因此停顿时间会变长;CMSFullGCBeforeCompaction设置第NFull GC后进行碎片整理

8.      G1收集器

1)       设计原则是:首先收集尽可能多的垃圾

2)       G1虽然是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念(每个分区都可能随G1的运行在不同代之间前后切换)

3)       G1使用分区(region)来组织堆内存

将整个堆空间分成若干个大小相等的区域

Ø 分配对象时逐段使用内存

Ø 对象的存储只是逻辑连续,物理上不一定连续

Ø 每个分区不固定为某个代服务,会按需切换

² 有年轻代分区占满时,JVM会分配新的空闲分区加入到年轻代空间

² 年轻代内存会在初始空间-XX:G1NewSizePercent(默认整堆5%)与最大空间-XX:G1MaxNewSizePercent(默认60%)之间动态变化,且由参数目标暂停时间-XX:MaxGCPauseMillis(默认200ms)、需要扩缩容的大小以及分区的已记忆集合(RSet)计算得到

² 设置固定的年轻代大小(参数-XX:NewRatio-Xmn),但同时暂停目标将失去意义

Ø 启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区

Ø 每个分区内部又被分成了若干个卡片(Card)

² 大小为512 Byte

² 堆内存最小可用粒度

² 所有分区的卡片将会记录在全局卡片表(Global Card Table)

² 分配的对象会占用物理上连续的若干个卡片

² 每次对内存的回收,都是对指定分区的卡片进行处理

每个Region被标记了E(Eden)S(Survivor)O(Old)H(humongous,存放巨型对象, 当新建对象大小超过Region大小一半时,直接在新的一个或多个连续Region中分配,并标记为H)

通过-Xms/-Xmx来指定堆空间大小

4)       G1的三种模式垃圾回收模式

young gc: 发生在年轻代的GC算法,一般对象(除了巨型对象)都是在eden region中分配内存,当所有eden region被耗尽无法申请内存时,就会触发一次young gc,这种触发机制和之前的young gc差不多,执行完一次young gc,活跃对象会被拷贝到survivor region或者晋升到old region中,空闲的region会被放入空闲列表中,等待下次被使用

mixed gc: 当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制, mixed gc中也有一个阈值参数 -XX:InitiatingHeapOccupancyPercent,当老年代大小占整个堆大小百分比达到该阈值时,会触发一次mixed gc

full gc: mixed gc来不及回收,导致老年代被填满,就会触发一次full gc(单线程执行的serial old gc)

以上是关于垃圾收集器的主要内容,如果未能解决你的问题,请参考以下文章

垃圾收集器(垃圾收集算法的实现)

垃圾收集器(垃圾收集算法的实现)

JVM之垃圾收集算法与垃圾收集器

JVM垃圾收集—垃圾收集器及常见组合参数

G1垃圾收集器介绍

JVM垃圾收集器