接上次JVM虚拟机堆内存模型来继续说,上次我们主要说了什么时候可能把对象直接放在老年代,还有我们的可能性分析,提出GCroot根的概念。这次我们主要来说说垃圾回收所使用的的算法和我们的垃圾回收器,需要了解我们的可达性分析GCroot根是什么,还有我们的动态年龄判断和老年代分配担保机制,还不清楚咋回事的小伙伴可以去我上几篇JVM的博客去看一下,JVM内存模型的几篇博客 https://www.cnblogs.com/cxiaocai/p/11520731.html

  垃圾回收算法,主要就三种,标记清除,复制,标记整理。

标记清除:

  上图说话。

解释一下,标记清理算法,我们可以视为每一个位置去观察,可以清理就标记,不能清理就放那不动。也可以想象为我们打扫屋子,我们只扔掉我们不想要的物品,其余想留下的东西还是放在原处不动。

这种算法清理缺点是效率并不高,而且会带来大量的空间碎片,我们可以由下面的小方格看到,红色的格子不是连续的,而是分布在不同位置的。这时进来一个大对象,需要多个连续的格子,就可能放不下了。

复制:

  不多了直接上图。

和上面相比,我们至少可以看到连续的红格子了,复制算法就是查看每一个小格子,可以回收就回收掉,不行就挪到保留的另一半内存中去,每次只标记整体区域的一半,我们还是拿收拾屋子举例,复制算法就像是,我们把卧室收拾一遍,不要的扔掉,想留下的整齐的放在客厅,下次我们收拾客厅也是如此,每次收拾一半。缺点就是内存利用率低,只能使用一半,还需要保留一半的区域为了来回挪动存活对象。

标记整理:

  

标记整理是是标记清除的升级版,优点:解决内存碎片问题。缺点:整理阶段,由于移动了可用对象,需要去更新引用。还是收拾屋子的那个例子,我们把没用的物品扔掉,其余物品整齐的摆放起来。

接下来就是和我们回收算法对应的回收器了。

Serial收集器(-XX:+UseSerialGC -XX:+UseSerialOldGC)

Serial(串行)垃圾收集器是最基本、发展历史最悠久的收集器;作用于新生代时采用采用复制算法;Serial Old收集器也就是Serial作用于老年代时采用标记整理算法。

采用单线程手机模式来收集。

ParNew收集器(-XX:+UseParNewGC) 

ParNew收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为 (控制参数、收集算法、回收策略等等)和Serial收集器完全一样。默认的收集线程数跟cpu核数相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般不推荐修改。 并且单核CPU的服务器,优先考虑Serial收集器,甚至由于存在线程交互的开销,效果不一定强于Serial收集器,可能Serial收集器效果更好,parNew新生代采用复制算法,老年代采用标记-整理算法。 建议使用在新生代,后面会说为什么。

Parallel Scavenge收集器(-XX:+UseParallelGC,- XX:+UseParallelOldGC)

Parallel Scavenge 收集器类似于ParNew 收集器,是Server 模式(内存大于2G,2个cpu)下的默认收集器, Parallel Scavenge更加关注于CPU的使用率,可能在回收的过程瞬间CPU使用率提高进行垃圾回收。Parallel Old收集器是Parallel Scavenge收集器的老年代版本。和上面的图一样 ,我就不再贴图了。新生代采用复制算法,老年代采用标记-整理算法。

CMS收集器(-XX:+UseConcMarkSweepGC(old)) 

  相对上面几个收集器来说稍微复杂一些,先看图。

由图来看确实复杂了不少,但是并不是一直处于STW阶段,中间还有并行的时候。我们来看一下每一个阶段都是做什么的。

初始化标记阶段:

  这里STW时间非常短,微乎其微的,这里只标记GCRoot根直接引用的对象,不往下层去搜索更多的对象进行标记,效率很高,STW时间很短。

并发标记阶段:

  并发标记阶段是最消耗时间的,在上一个阶段只标记GCRoot根的直接引用对象,这个阶段是把所有需要回收的对象都需要标记出来。可能引用很多,所以耗时较大。但是还好,他不会出现STW,不会停掉所有线程为其单一服务。

重新标记阶段:

  在上一个相对比庞大的并发标记阶段,并没有STW,可能会产生新的GCRoot根,或者说原有不需要回收的对象现在已经变为垃圾对象了,我们在重新标记阶段再一次来做一下处理,这里又会出现STW现象,相比并发标记阶段时间也是很短的。

并发清理阶段:

  恢复我们的正常的线程,开始清理没有标记的对象,这里不会产生STW,在这个阶段再进来的新对象,或者产生对象的变更,CMS是不会继续处理的,会在下一次垃圾回收再来处理这些对象。

并发重置阶段:

  清楚所有标记,为下一次垃圾回收做准备。

CMS垃圾收集器步骤比较多,但是我们可以看出明显提高了效率,中间至少不是持续的STW的。但是也有CMS的弊端的,并发标记阶段和并发清理阶段很容易和我们正常的线程抢占CPU的。再就是他的算法只是标记清理,并没有整理内存碎片,但可以调配参数做到整理碎片的目的。最坑的问题来了,就是我们在并发标记阶段,可能进来新的对象,本来我们老年代就快满了,才进行的垃圾收回,这时这些对象过大过多,会再次执行CMS的垃圾回收,造成concurrent mode failure,这时会变更为Serial收集器,产生较长的STW时间。

CMS相关参数:

1. -XX:+UseConcMarkSweepGC:启用cms垃圾回收器
2. -XX:ConcGCThreads:并发的GC线程数目
3. -XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)
4. -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次
FullGC后都会压缩一次,依赖上面的参数,必须配置-XX:+UseCMSCompactAtFullCollection才生效
5. -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认
是92,这是百分比),可能出现JVM自我优化变更的现象,不是很稳定
6. -XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整,比上面的-XX:CMSInitiatingOccupancyFraction稳定很多
7. -XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,目的在于减少
老年代对年轻代的引用,降低CMS GC的标记阶段时的开销,一般CMS的GC耗时 80%都在重新标记阶段

今天先说这么多 ,还有一个G1收集器没有说,下次博客会说G1收集器,和常见的调优方式,有时间我再整理一份常用的命令。

看起来真的吃力的话,建议先看一下我前几篇JVM相关的博客,JVM内存模型的几篇博客 https://www.cnblogs.com/cxiaocai/p/11520731.html

java架构之路-(12)JVM垃圾回收算法和垃圾回收器的更多相关文章

  1. java架构之路-(JVM优化与原理)JVM之G1回收器和常见参数配置

    过去的几天里,我把JVM内部的垃圾回收算法和垃圾回收器.还剩下最后一个G1回收器没有说,我们今天数一下G1回收器和常见的参数配置. G1回收器 G1 (Garbage-First)是一款面向服务器的垃 ...

  2. JVM 垃圾回收算法和垃圾回收器

    JVM 垃圾回收算法和垃圾回收器. 一.垃圾回收的区域 栈:栈中的生命周期是跟随线程,所以一般不需要关注. 堆:堆中的对象是垃圾回收的重点. 方法区:这一块也会发生垃圾回收,不过这块的效率比较低,一般 ...

  3. 直通BAT必考题系列:JVM的4种垃圾回收算法、垃圾回收机制与总结

    垃圾回收算法 1.标记清除 标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段. 在标记阶段首先通过根节点(GC Roots),标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象. ...

  4. java中的垃圾回收算法与垃圾回收器

    常用的垃圾回收算法 标记-清除 标记清除算法是一种非移动式的回收算法,分为标记 清除 2个阶段,简而言之就是先标记出需要回收的对象,标记完成后再回收掉所有标记的内存对象,如下图 可见回收后图中被标记的 ...

  5. Java垃圾回收算法和垃圾回收器

    基本上 jvm内存回收有三种 基本算法 标记-清除 标记清除的算法最简单,主要是标记出来需要回收的对象,然后然后把这些对象在内存的信息清除.如何标记需要回收的对象,在上一篇文章里面已经有说明. 标记- ...

  6. java架构之路-(JVM优化与原理)JVM类的加载机制

    话不多说,先上图. ***.class文件执行大概就是这样来走的.我们都知道我们的java文件经过编译以后会生成对应的class文件.先经过类装载子系统,然后塞进运行时内存模型的元空间,开始执行方法, ...

  7. java架构之路-(JVM优化与原理)JVM的运行时内存模型

    还是我们上次的图,我们上次大概讲解了类加载子系统的执行过程,验证,准备,解析,初始化四个过程.还有我们的双亲委派机制. 我们这次来说一下运行时内存模型.上一段小代码. public class Mai ...

  8. Java垃圾回收算法和内存分配策略

    垃圾回收算法和内存分配策略 Java垃圾回收 垃圾收集,也就是GC并不是Java的伴生物,而对于GC的所需要完成任务主要就是: 1.哪些内存是需要回收的? 2.何时去回收这些内存? 3.以何种方式去回 ...

  9. JVM学习总结二——垃圾回收算法

    昨天总结了JVM内存分区相关的知识,这次我们将来了解下JVM的另一个核心知识点——垃圾回收算法.这一部分其实并不太难,如果对操作系统的内存处理算法有所了解,那么这部分算法其实只看名字就能明白,两者在原 ...

随机推荐

  1. 如何删除GIT仓库中的敏感信息

    如何删除GIT仓库中的敏感信息 正常Git仓库中应该尽量不包含数据库连接/AWS帐号/巨大二进制文件,否则一旦泄漏到Github,这些非常敏感信息会影响客户的信息安全已经公司的信誉.公司可能其它还有相 ...

  2. 基于Visual C#的AutoCAD开发——一些网址

    https://blog.csdn.net/xwebsite/article/details/5578446 http://www.cadgj.com/?p=1504

  3. serverless在微店node领域的探索应用

    背景 目前微店中台团队为了满足公司大部分产品.运营以及部分后端开发人员的尝鲜和试错的需求,提供了一套基于图形化搭建的服务端接口交付方案,利用该方案及提供的系统可生成一副包含运行时环境定义可立即运行的工 ...

  4. 激活Cisco路由器和交换机的right-to-use

    一.确认当前正在使用license版本 show license     #路由器2911测试可行 show license summary #交换机C4503测试可行 show version  # ...

  5. js中toFixed精度问题的解决办法

    toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为:toFixed(Num):但是其四舍五入的规则与数学中的规则不同,使用的是银行家舍入规 ...

  6. css布局之居中

    CSS布局之居中 本文主要是介绍水平居中,垂直居中,还有水平垂直居中的方法 水平居中 1.行内元素水平居中 使用text-align:center;就可以实现行内元素的水平居中,但是记得要在父元素中设 ...

  7. Flink的Job启动Driver端(源码分析)

    整个Flink的Job启动是通过在Driver端通过用户的Envirement的execute()方法将用户的算子转化成StreamGraph,然后得到JobGraph通过远程RPC将这个JobGra ...

  8. python 14 装饰器

    目录 装饰器 1. 开放封闭原则 装饰器 1. 开放封闭原则 扩展是开放的,增加新的功能:修改源码(修改已经实现的功能)是封闭的. 在不改变源码及调用方式的前提下额外增加新的功能. # 版一: imp ...

  9. Java集合框架之Map接口浅析

    Java集合框架之Map接口浅析 一.Map接口综述: 1.1java.util.Map<k, v>简介 位于java.util包下的Map接口,是Java集合框架的重要成员,它是和Col ...

  10. 如何理解JS中this指向的问题

    首先,用一句话解释this,就是:指向执行当前函数的对象. 当前执行,理解一下,也就是说this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定.this到底指向谁?this的最终指向的 ...