JVM学习-垃圾回收器

1.垃圾回收器概述

垃圾回收发生时,其他线程都暂停。STW是指stop the world的时间,即垃圾回收的时间
1.串行
单线程
堆内存较小,适合个人电脑(CPU核数较少)

2.吞吐量优先
多线程:
适合堆内存较大,需要多核CPU支持(只有单核的话,那么还要争抢,效率还不如单核CPU),适合工作在服务器上
让单位时间内,STW的时间最短。

3.响应时间优先
多线程
堆内存较大,多核CPU,适合工作在服务器上
尽可能让STW的单次时间最短。
注意:吞吐量优先和响应时间优先的区别,举个例子,响应时间优先可能每次STW的时间为0.1s,但是1小时内总共发生了5次,而吞吐量优先每次发生了0.2s,但1小时内仅发生了2次。吞吐量优先在总时间上似乎优于响应时间优先。

2.串行

单线程
内存较小,个人电脑(CPU核数较少)
开启串行垃圾回收器语句/参数:-XX:+UseSerialGC=Serial+SerialOld
Serial工作在新生代,采用复制算法。SerialOld工作在老年代,采用标记整理算法。

在这里插入图片描述
安全点:让其他线程都在这个点停下来,以免垃圾回收时移动对象地址,使得其他线程找不到被移动的对象

因为是串行的,所以只有一个垃圾回收线程。且在该线程执行回收工作时,其他线程进入阻塞状态

Serial 收集器
Serial收集器是最基本的、发展历史最悠久的收集器

特点**:单线程、简单高效(与其他收集器的单线程相比),采用复制算法。**对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程手机效率。收集器进行垃圾回收时,必须暂停其他所有的工作线程,直到它结束(Stop The World)

ParNew 收集器
ParNew收集器其实就是Serial收集器的多线程版本

特点:多线程、ParNew收集器默认开启的收集线程数与CPU的数量相同,在CPU非常多的环境中,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。和Serial收集器一样存在Stop The World问题

扫描二维码关注公众号,回复: 12444363 查看本文章

Serial Old 收集器
Serial Old是Serial收集器的老年代版本

特点:同样是单线程收集器,采用标记-整理算法

3.吞吐量优先

多线程
堆内存较大,多核CPU
单位时间内,STW(stop the world,停掉其他所有工作线程)时间最短
JDK1.8默认使用的垃圾回收器

-XX:+UserParallelGC~-XX:+UserParallelOldGC
UserParallelGC新生代采用复制算法。UserParallelOldGC采用的是标记整理算法。

工作模式:假如4个线程都在跑,内存不足触发一次垃圾回收,此时用户线程都会跑到安全点停下来,不一样之处在于垃圾回收器会开启多个垃圾回收线程来进行垃圾回收。垃圾回收线程通常与CPU核数相同。

Parallel Scavenge 收集器
与吞吐量关系密切,故也称为吞吐量优先收集器

特点:属于新生代收集器也是采用复制算法的收集器(用到了新生代的幸存区),又是并行的多线程收集器(与ParNew收集器类似)

该收集器的目标是达到一个可控制的吞吐量。还有一个值得关注的点是:GC自适应调节策略(与ParNew收集器最重要的一个区别)

GC自适应调节策略:Parallel Scavenge收集器可设置-XX:+UseAdptiveSizePolicy参数。当开关打开时不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、晋升老年代的对象年龄(-XX:PretenureSizeThreshold)等虚拟机会根据系统的运行状况收集性能监控信息,动态设置这些参数以提供最优的停顿时间和最高的吞吐量,这种调节方式称为GC的自适应调节策略

Parallel Scavenge收集器使用两个参数控制吞吐量:

XX:MaxGCPauseMillis 控制最大的垃圾收集停顿时间
XX:GCRatio 直接设置吞吐量的大小
Parallel Old 收集器
是Parallel Scavenge收集器的老年代版本

特点:多线程,采用标记-整理算法(老年代没有幸存区)

4.响应时间优先(CMS重点)

-XX:+UseConcMarkSweepGC~-XX:+UseParNewGC ~SerialOldOld
CocurrentMarkSweep并发标记清除算法UseConcMarkSweepGC:它是并发的基于标记清除算法的老年代垃圾回收器。Parrllel是并行的,这是并发的。并发是指垃圾回收的同时,其它用户进程也能同时进行。用户线程和垃圾回收线程可以同时工作(宏观上)。就进一步减少了stop the world的时间。它是工作在老年代的垃圾回收器
UseParNewGC它是工作在新生代的基于复制算法的垃圾回收器。
CMS垃圾回收器有时会发生并发失败的问题。这时它就会采取补救的措施,让老年代的垃圾回收器从并发退化到SerialOld单线程的垃圾回收器,即基于标记整理的老年代的垃圾回收器

CMS 收集器特性总结:
Concurrent Mark Sweep,一种以获取最短回收停顿时间为目标的老年代收集器

特点:基于标记-清除算法实现。并发收集、低停顿,但是会产生内存碎片

应用场景:适用于注重服务的响应速度,希望系统停顿时间最短,给用户带来更好的体验等场景下。如web程序、b/s服务
在这里插入图片描述

CMS收集器的运行过程分为下列4步:

初始标记:标记GC Roots能直接到的对象。速度很快但是仍存在Stop The World问题
初始标记只去标记根对象直接到的对象,所以非常快。

并发标记:进行GC Roots Tracing 的过程,找出存活对象且用户线程可并发执行

重新标记:为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。仍然存在Stop The World问题

并发清除:对标记的对象进行清除回收

参数-XX:ParallelGCThreads=n~-XX:ConcGCThreads=threads
ParallelGCThreads并行的垃圾回收线程数,与CPU核数相同,一般是4,ConcGCThreads并发的GC线程数一般设置为并行线程数的1/4。

CMS垃圾回收工作时对CPU的占用率不如Parallel高。4核的CPU只占用了1核进行垃圾回收。用户只能占用3/4的CPU核数,整个系统的用户吞吐量是有影响的,本来四核完成逻辑计算,本来只需要花1s时间,但是其中1核给垃圾回收用了,可用于计算的就少了,计算同样的就会花更多的时间。对整个系统的吞吐量就会有影响。

CMSInitiatingOccupancyFraction=percent,触发CMS的内存占比,要预留一些空间给浮动空间。
CMSScavengBeforeRemark:在重新标记之前,对新生代做垃圾回收

CMS缺点:在内存碎片比较多的情况下(因为基于标记清除算法),将来新生代内存不足,而老年代内存也不足,就会造成并发失败,CMS垃圾回收器就不能正常工作了,就会退化在SerialOld单线程的串行的垃圾回收器,做一次整理,整理完了,才能继续工作,一旦发生了并发失败的问题,垃圾回收的时间就会迅速上升。然而我们的初衷就是尽可能的减少响应时间。

猜你喜欢

转载自blog.csdn.net/qq_39736597/article/details/113484071