JVM垃圾收集器

垃圾回收算法是内存回收的方法论,而收集器是内存会说欧的具体实现,Java虚拟机规范中对垃圾回收器没有任何规定,不同厂商,不同版本的虚拟机都会有很大的差别。
下图是各种垃圾收集器的搭配使用的关系。
这里写图片描述

Serial收集器:
这里写图片描述
Serial Garbage Collector:
算法:采用复制算法
内存区域:针对新生代设计
执行方式:单线程、串行
执行过程:当新生代内存不够用时,先暂停全部用户程序,然后开启一条GC线程使用复制算法对垃圾进行回收,这一过程中可能会有一些对象提升到年老代
特点:由于单线程运行,且整个GC阶段都要暂停用户程序,因此会造成应用程序停顿时间较长,但对于小规模的程序来说,却非常适合。
适用场景:平时的开发与调试程序使用,以及桌面应用交互程序。
开启参数:-XX:+UseSerialGC(client模式默认值)

Serial Old Garbage Collector:
与serial搜集器是一样的,区别是它是针对年老代而设计的,因此采用标记/整理算法。

ParNew收集器:
这里写图片描述
其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾回收机外,其余一模一样。

ParNew Garbage Collector
算法:采用复制算法
内存区域:针对新生代设计
执行方式:多线程、并行
执行过程:当新生代内存不够用时,先暂停全部用户程序,然后开启若干条GC线程使用复制算法并行进行垃圾回收,这一过程中可能会有一些对象提升到年老代
特点:采用多线程并行运行,因此会对系统的内核处理器数目比较敏感,至少需要多于一个的处理器,有几个处理器就会开几个线程(不过线程数是可以使用参数-XX:ParallelGCThreads=控制的),因此只适合于多核多处理器的系统。尽管整个GC阶段还是要暂停用户程序,但多线程并行处理并不会造成太长的停顿时间。因此就吞吐量来说,ParNew要大于serial,在处理器越多的时候,效果越明显。但是这并非绝对,对于单个处理器来说,由于并行执行的开销(比如同步),ParNew的性能将会低于serial搜集器。不仅是单个处理器的时候,如果在容量较小的堆上,甚至在两个处理器的情况下,ParNew的性能都并非一定可以高过serial。
适用场景:在中到大型的堆上,且系统处理器至少多于一个的情况
开启参数:-XX:+UseParNewGC
Parallel Scavenge 收集器:
Parallel Scavenge Garbage Collector
这个搜集器与ParNew几乎一模一样,都是针对新生代设计,采用复制算法的并行搜集器。它与ParNew最大的不同就是可设置的参数不一样,它可以让我们更精确的控制GC停顿时间以及吞吐量。
parallel scavenge搜集器提供参数主要包括控制垃圾回收器最大的停顿时间(使用-XX:MaxGCPauseMillis=),以及控制吞吐量(使用-XX:GCTimeRatio=)。由此可以看出,parallel scavenge就是为了提供吞吐量控制的搜集器。
不过大家千万不要以为把最大停顿时间调的越小越good,或者吞吐量越大越好,在使用parallel scavenge搜集器时,主要有三个性能指标,最大停顿时间、吞吐量以及新生代区域的最小值。
parallel scavenge搜集器具有相应的调节策略,它将会优先满足最大停顿时间的目标,次之是吞吐量,最后才是新生代区域的最小值。
因此,如果将最大停顿时间调的过小,将会牺牲整体的吞吐量以及新生代大小来满足你的私欲。手心手背都是肉,我们最好还是不要这么干。不过parallel scavenge有一个参数可以让parallel scavenge搜集器全权接手内存区域大小的调节,这其中还包括了晋升为年老代(可使用-XX:MaxTenuringThreshold=n调节)的年龄,也就是使用-XX:UseAdaptiveSizePolicy打开内存区域大小自适应策略。
parallel scavenge搜集器可使用参数-XX:+UseParallelGC开启,同时它也是server模式下默认的新生代搜集器。
Parallel Old Garbage Collector
Parallel Old与ParNew或者Parallel Scavenge的关系就好似serial与serial old一样,相互之间的区别并不大,只不过parallel old是针对年老代设计的并行搜集器而已,因此它采用标记/整理算法。
Parallel Old搜集器还有一个重要的意义就是,它是除了serial old以外唯一一个可以与parallel scavenge搭配工作的年老代搜集器,因此为了避免serial old影响parallel scavenge可控制吞吐量的名声,parallel old就作为了parallel scavenge真正意义上的搭档。
它可以使用参数-XX:-UseParallelOldGC开启,不过在JDK6以后,它也是在开启parallel scavenge之后默认的年老代搜集器。
Concurrent Mark Sweep Garbage Collector
concurrent mark sweep(以下简称CMS)搜集器是唯一一个真正意义上实现了应用程序与GC线程一起工作(一起是针对客户而言,而并不一定是真正的一起,有可能是快速交替)的搜集器。
CMS搜集器
CMS是针对年老代设计的搜集器,并采用标记/清除算法,它也是唯一一个在年老代采用标记/清除算法的搜集器。
采用标记/清除算法是因为它特殊的处理方式造成的,它的处理分为四个阶段。
1、初始标记:需要暂停应用程序,快速标记存活对象。
2、并发标记:恢复应用程序,并发跟踪GC Roots。
3、重新标记:需要暂停应用程序,重新标记跟踪遗漏的对象。
4、并发清除:恢复应用程序,并发清除未标记的垃圾对象。
它比原来的标记/清除算法复杂了点,主要表现在并发标记和并发清除这两个阶段,而这两个阶段也是整个GC阶段中耗时最长的阶段,不过由于这两个阶段皆是与应用程序并发执行的,因此CMS搜集器造成的停顿时间是非常短暂的。这点还是比较好理解的。

垃圾收集器组合

serial & serial old
这个组合是我们最常见的组合之一,也是client模式下的默认垃圾搜集器组合,也可以使用参数-XX:+UseSerialGC强制开启。
没有线程相关的额外开销(主要指线程切换与同步),适合运行于客户端PC的小型应用程序,或者桌面应用程序(比如swing编写的用户界面程序),以及我们平时的开发、调试等。
上面三种情况都有共同的特点。
1、由于都是在PC上运行,因此配置一般不会太高,或者说处理器个数不会太多。
2、上面几种情况的应用程序都不会运行太久。
3、规模不会太大,也就是说,堆相对较小,搜集起来也比较快,停顿时间会比较短。

Parallel Scavenge & Parallel Old
这个组合我们并不常见,毕竟它不会出现在我们平时的开发当中,但是它却是很多对吞吐量(throughout)要求较高或者对停顿时间(pause time)要求不高的应用程序的首选,并且这个组合是server模式下的默认组合(JDK6或JDK6之后)。当然,它也可以使用-XX:+UseParallelGC参数强制开启。
该组合无论是新生代还是年老代都采用并行搜集,因此停顿时间较短,系统的整体吞吐量较高。它适用于一些需要长期运行且对吞吐量有一定要求的后台程序。
这些运行于后台的程序都有以下特点。
1、系统配置较高,通常情况下至少四核(以目前的硬件水平为准)。
2、对吞吐量要求较高,或需要达到一定的量。
3、应用程序运行时间较长。
4、应用程序规模较大,一般是中到大型的堆。
ParNew & CMS(Serial Old作为替补)
这个组合与上面的并行组合一样,在平时的开发当中都不常见,而它则是对相应时间(response time)要求较高的应用程序的首选。该组合需要使用参数-XX:+UseConcMarkSweepGC开启。
该组合在新生代采用并行搜集器,因此新生代的GC速度会非常快,停顿时间很短。而年老代的GC采用并发搜集,大部分垃圾搜集的时间里,GC线程都是与应用程序并发执行的,因此造成的停顿时间依然很短。它适用于一些需要长期运行且对相应时间有一定要求的后台程序。
这些运行于后台的程序的特点与并行模式下的后台程序十分类似,不同的是第二点,采用ParNew & CMS组合的后台应用程序,一般都对相应时间有一定要求,最典型的就是我们的WEB应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值