个人全部文章同步更新与Github--Java-Notes,想了解JVM,HashMap源码分析,spring相关,剑指offer题解(Java版),能够点个star。能够看个人github主页,天天都在更新哟。git
邀请您跟我一同完成 repogithub
阅读本篇文章,你首先的知道这两个概念算法
若是不了解垃圾回收算法或者是断定对象存活的可达性分析算法,能够参看个人这篇博文,垃圾回收spring
垃圾回收器是垃圾回收的具体实现,这里只讲Hotspot虚拟机的7中不一样的垃圾回收器。安全
虚拟机使用的时候是采用组合的方式,可是也不是能够随意组合的,组合方式以下多线程
从名字能够看出来他是一个单线程的收集器(Serial有串行的意思),他在工做的时候,用户的其余全部工做线程都必须中止。这也是"Stop the World"的由来。并发
可是这种的工做方式让人听难受的,你想一想你工做的时候正在兴头上,立刻高潮了,忽然戛然而止。GC线程出来工做了,你一动不能动。由于它自动发起的,自动完成的,用户不可见,不可预知。源码分析
下面用图给你解释下。(Serial搭配Serial Old)性能
若是不了解标记复制算法或者安全点能够查看个人这篇博文--垃圾回收算法网站
多线程版 Serial收集器
不少server模式下首选的新生代收集器
其余和Serial同样
多线程版不必定意味着比单线程的Serial的效率高,由于他有别的线程的频繁交互,随着CPU的增多,才会比他的效率高
吞吐量优先(最大的特点)
自动调节适应
多线程
你能够把收集过程和ParNew差很少,图片也差很少。可是他有两个特点
其余收集器关注的是减小垃圾收集时用户停顿的时间。而他关注的是达到一个可控的吞吐量
吞吐量是CPU运行用户代码的时间与CPU消耗的总时间的比值
吞吐量 = 运行用户代码的时间 / (运行用户代码+垃圾回收的时间)。
虚拟机总共运行了 100s,垃圾回收用了 1s,那吞吐量就为99%
由两个参数控制
根据名字就能够看出来啊,第一个是说回收时的暂停时间、单位毫秒,第二个是回收时间所占的比例。
可是第一个设置的越小,垃圾回收越频繁,总时间不必定会降低。应该很好理解
第二个是GC时间比例,至关于吞吐量的倒数。范围(1,100)的整数。若是设置为1,值为50%=1/(1+1)。默认为99,即容许回收时间占1% = 1/(1+99).
参数:-XX:UseAdaptiveSizePolicy
若是打开,那么你就能够不用本身手工去指定新生代的大小、Eden和Survivor区的比例、晋升老年代对象大小(若是一个对象足够大,那么能够直接在老年代分配)。
若是对于收集器的运做不太了解,那么能够打开这个参数,交给虚拟机本身完成
图片参考 Serial
这个收集器是在JDK1.6以后才提供,没有提供以前 新生代的Parallel Scavenge的地位比较尴尬。还记得我一开始的图吗,若是没有这个收集器,新生代的 Parallel 只能选择 Serial,他和 CMS 不兼容。可是Serial Old 这个收集器在多线程模式下,以及老年代很大的状况下的性能算是表现比较差的。通常选择组合都去用 PerNew + CMS
了,他就很尴尬。
到了JDK1.6以后,在注重吞吐量以及CPU资源敏感的场合,能够优先考虑Parallel组合了,这个时候 Serial Old ,在server模式下就做为CMS的后备方案,在并发收集时发生 Concurrent Mode Failure 的时候使用(介绍CMS的时候我会说明)
图片描述以下图所示
CMS(Concurrent Mark Sweep)是一款以获取最短回收停顿时间为目标的收集器。很是符合在很大一部分的Java应用集中在互联网站或者B/S系统的服务端上应用的需求。由于这种的应用尤为重视服务的响应速度,但愿停顿时间短,以此带来更好的用户体验
记住:其中 初始标记和从新标记是须要"Stop The World",不过期间很短
初始标记的过程仅仅标记GC Root直接关联的对象,他并不去标记间接关联的。这个过程交给第二阶段并发标记来完成;
从新标记阶段则是为了修正并发标记期间因用户程序继续运做而致使标记产生变更的那一部分对象的标记记录,停顿时间比第一阶段的初始标记稍长。
第四个阶段,并发清除。也是能够并发完成的。
由于在这里第一次出现并发的概念,我解释一下在垃圾回收的时候并发和并行的概念。注意只是垃圾回收中的并行并发。
并行是,多个回收线程工做,工做线程不工做。
并发是,回收线程和工做线程一块儿工做。
因此你能够说 ParNew 是并行的收集器,但不能说是并发的收集器
收集器工做图解以下图所示
若是CPU资源不多,可开启线程也不多。那么CMS会让用户体验很是差,由于要分出至关多的资源去运行垃圾回收,致使运行程序的资源变少。
由于他是并发进行回收的,因此当我在收集时,你还在产生垃圾,那么这部分垃圾被称为的浮动垃圾。而这部分垃圾不得不在我下一次回收时才能回收。并且他也不能充分利用空间,毕竟要分一部分给浮动垃圾,因此若是垃圾过多,空间不能知足,就会出现"Concurrent Mode Failure"提早触发一次 Full GC,这个过程会启动 Serial Old进行收集。
G1(Garbage First)是一款面向服务端应用的垃圾收集器。在JDK1.9被设置成默认的垃圾回收器,基本算是最前沿的垃圾回收器。固然还有更牛逼的垃圾回收器ZGC。不过他是在JDK 11 才被推出,因此通常人用不到,也不用了解,想了解能够看下这篇文章,JDK11的ZGC
咱们先看传统的年代分割
(JDK1.8以后已经移除了永久代,改成元空间了)
下面是G1的分割
经过图片能够看出来,以前的垃圾回收器的年代是空间(逻辑上)连续的,而G1的空间是不连续的,他被划分为一个个大小相等的 region
**从总体上看,他是采用"标记-整理算法",局部(两个region之间)看是"标记-复制算法"。**因此G1运做期间不会产生内存碎片。
可预测的停顿:是指用户能够指定整个GC过程的指望停顿时间,经过参数-XX:MaxGCPauseMillis
,那么他是怎么知足用户指望的时间呢?就须要停顿预测模型了。G1根据这个模型统计计算出来的历史数据来预测本次收集须要选择的Region数量,从而尽可能知足用户设定的目标停顿时间
先用一张图解释一下步骤
从图中咱们能够看到,G1的过程和CMS差很少,可是仍是有一些区别,主要是最后的清理阶段,他也是STW(Stop The World)的。其余更多的是算法的差异。