栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

JVM垃圾回收器

Java 更新时间:发布时间: 百科书网 趣学号

目录

串行垃圾回收器(Serial Collector)

并发式垃圾回收器

 7种经典垃圾回收器

Serial 收集器

ParNew收集器

Parallel Scavenge收集器

CMS收集器

G1收集器

小结

常用参数


按垃圾回收器的线程数可以分为串行垃圾回收器和并行垃圾回收器。

串行垃圾回收器(Serial Collector)

        串行回收指在同一时间段内只有一个CPU用于执行垃圾回收操作,这时候工作线程被暂停,直到垃圾收集工作结束。串行垃圾回收器常常被用在单CPU处理器或内存比较小的硬件平台。

并行垃圾回收器(Parallel Collector)

        并行回收是指在同一段时间内有多个CPU同时用于垃圾回收,虽然提高了吞吐量,但是还是存在“Stop The World”的问题。

        按工作模式可以分为并发式垃圾回收器和独占式垃圾回收器。

并发式垃圾回收器

        并发式垃圾回收器可以与应用程序交替工作,可以尽量减少程序的卡顿时间。

独占式垃圾回收器

        独占式垃圾回收器(Stop The World)一旦执行,就停止程序中的所有用户线程,直到垃圾回收工作结束后用户线程才恢复工作。

7种经典垃圾回收器

Serial 收集器

            Serial串行收集器,适合于单核CPU的客户端端,是HotSpot最早退出的一款垃圾收集器。一般用于嵌入式,单核CPU的场景,一般搭配Serial Old 一起使用,但是这款垃圾收集器在现代的多CPU服务器环境下用得非常少了。 

ParNew收集器

        ParNew收集器与Serial收集器非常像,Serial收集器是单线程的,ParNew是多线程的。Par是Paraller的缩写,New表示只能处理新生代。ParNew收集器在新生代中也是采用复制算法,同样存在“Stop The World”的问题。

        ParNew更适合在多CPU的服务器,Serial更适合用于单CPU的服务器(如嵌入式,client客户端等)。ParNew在多CPU环境下能够充分利用多CPU的物理硬件优势快速完成垃圾收集,但是在单CPU环境下存在线程切换的额外开销,导致效率不一定比Serial快。而Serial虽然能够部署在多CPU服务器,但是没办法充分利用CPU核数优势,只是使用单核资源,比不上ParNew高效。

        在JDK9之后,老年代不再搭配Serial Old。

        ParNew 收集器在jdk8及之后用得非常少,jdk9已经不再推荐使用。

Parallel Scavenge收集器

        Parallel Scavenge收集器同样采用了复制算法,并行收集,也存在“Stop The World"问题。与ParNew收集器不同,Parallel Scavenge设计出来是吞吐量优先的垃圾收集器。

        高吞吐量可以更高效地利用CPU时间,尽快完成任务,主要用于后台运行而不需要太多交互的任务。比如批量处理,订单处理,后台定时任务等场景。

        jdk6之后提供了Parallel Old收集器用于替换serial old收集器,以便老年代的垃圾收集提高效率。因此一般都是Parallel Scavenge和Parallel Old搭配使用,jdk8默认的就是这种垃圾收集器。

CMS收集器

        是在JDK1.5,HotSpot虚拟机推出的一款在强交互应用中具有划时代意义的垃圾收集器,CMS(Concurrent-Mark-Sweep)收集器,是HotSpot虚拟机中第一款真正意义上的并发收集器,第一次实现了垃圾收集线程与用户线程同时工作。

        CMS收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间。用户线程停顿时间越短,就越适合于与用户交互的程序。目前主要适合于互联网网站或一些B/S系统的服务端,适合于比较重视服务响应速度,希望系统卡顿时间短的应用。

        jdk9之后已经废弃了CMS收集器,默认的收集器已经改为了G1收集器。在jdk14已经删除了CMS收集器。

        CMS垃圾收集器采用标记-清除算法,也会存在“Stop The World”的问题。        

        CMS工作原理,主要分为以下4个阶段:

        1.初始标记:在这个阶段,所有的工作线程都会因为“Stop The World”停止,然后标记出GC Roots 能够关联的对象,一旦标记完成,所有的被暂停的工作线程又恢复工作,这个过程非常快。

        2.并发标记:把GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程比较耗时但是无需停止工作线程。

        3.重新标记:这个过程是为了修复并发标记阶段中,因用户线程继续工作而导致标记对象产生变动导致在GC Roots中变为不可达或可达的对象,只保留可达对象。也存在“Stop The World”的情况,这个过程比初始标记的耗时要多,但是比并发标记的耗时少。

        4.并发清除:清理删除标记阶段判断的已经死亡的对象,释放内存。

        特点:

        1.由于并发标记和并发清除阶段,无需“Stop The World”,所以整体回收是低停顿的。

        2.由于在垃圾收集阶段用户线程是没有中断的,在CMS回收过程中,还应该确保用户线程又足够的内存空间,要是没有足够的内存空间,CMS垃圾收集器就会临时启用Serial Old收集器来重新进行老年代的垃圾收集,导致卡顿时间边变长。

        3.由于采用了标记-清除算法,导致内存回收后所释放的内存空间存在不连续的情况。

        4.为什么不采用标记-压缩算法?是因为在标记阶段无需停止用户线程,就不能移动对象在内存中的位置,采用压缩算法是需要把不可达对象删除,在内存中把可达对象移动到相对连续的位置,然后留下较大的内存空间。

G1收集器

        官方推出G1(Garbage First)收集器的目标是在延迟可控的情况下获得尽可能高的吞吐量(即在有限的暂停时间内获得最大的吞吐量)。 G1收集器把内存分割为多个不相关的区域(region),使用不同的region表示Eden,survior0,survior1,老年代等,;G1中的新生代老年代这些堆内存物理上是不连续的逻辑上是连续的。避免在整个java堆中进去全区域的垃圾收集,G1与过去的Parallel,CMS等收集器的内存模型差别非常大,是按region区进行GC Roots检索,每次垃圾收集时都是检查部分的region,这样的耗时就比较小。旧的垃圾收集器是当新生代或老年代快满的时候才进行垃圾收集,是对整个新生代或老年代堆进行GC Roots可达性检索非常耗时。

        

        region区:region分为Eden,Survior,Old,Humongous内存区域,每一个region就是这些内存区域的一个角色,Humongous区域比较特殊,是G1用来存放大对象的内存区域,当大对象超过1.5个region时,就会放到Humongous区。

        G1收集器适合在具有大内存多处理器的机器上的程序,非常适合要求GC停顿时间少的场景,但是内存一般在6G以下的表现甚至不如CMS收集器,当内存大于等于6G时表现就比较好。

        G1收集器是jdk7推出的,但是在jdk9才是默认的垃圾收集器。

小结

        最小化使用内存和并行开销:Serial GC

        最大化程序吞吐量:Parallel Scavenge GC

        最小化GC停顿时间:CMS GC

        JKD9之后用G1(ZGC还未成熟,等到官方默认使用ZGC的jdk版本之后再使用ZGC吧)

常用参数

                -XX:+UseSerialGC 开启Serial收集器,新生代为Serial,老年代为Serial Old。

                -XX:+UseParNewGC    开启新生代使用ParNew收集器

                -XX:ParallelGCThreads ParNew收集器线程数量,默认是与CPU核数相同

                -XX:+UseParallelGC 开启新生代使用Parallel Scavenge收集器,jdk8默认开启。

                -XX:+UseParallelOldGC 开启老年代使用Parallel Old收集器,jdk8默认开启。

                                -XX:+UseParallelGC 和  -XX:+UseParallelOldGC 任意一个开启后,另外一个默认也开启。

                -XX:MaxGCPauseMillis 设置Parallel Scavenge收集器的最大停顿时间(Stop The World)

                -XX:GCTimeRatio 设置Parallel Scavenge收集器的垃圾收集时间占总时间的比例,默认值是99,也就是垃圾收集时间不超过1%,与  -XX:MaxGCPauseMillis 有一定的矛盾,暂停时间越长,  -XX:GCTimeRatio 就越有可能超过限制。

                -XX:+UseConcMarkSweepGC 开启使用CMS垃圾回收器,开启这个参数后会自动开启-XX:+UseParNewGC,即ParaNew(新生代) + CMS(老年代) +Serial Old(老年代备用)的组合。

                -XX:CMSlnitiatingOccupanyFraction 表示CMS垃圾收集器的堆内存使用率阈值,一旦达到该阈值就开始回收,在jdk5时默认是68,表示堆内存使用率达到68%时会执行一次CMS回收,jkd6之后是92。如果内存增长缓慢,可以设置一个较大的阈值,较大的阈值能够减少CMS的执行频率,减少老年代的回收次数从而较为明显的改善程序性能。如果内存增长非常快,在要降低阈值,避免频繁触发老年代串行收集器。

                -XX:useG1GC 开启G1垃圾收集器

                -XX:G1HeapRegionSize        设置G1收集器的每个Region大小,值是2的幂,范围是1M-32M之间,默认是堆的1/2000。

                -XX:MaxGCPauseMillis        设置G1收集器最大的停顿时间,默认是200ms。

                

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/1073052.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号