接上次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. Sqlserver 使用.net查询被事务锁住处理

    在有些应用场景中.事务开了后或能需要再去调用某个DAL读取表中的数据.但DAL里又是新开的链接,由于外面有事务所以这里读的时候就读不到.这种情况下可以在这个DAL的查询里开一个新的事务级别设为允许脏读 ...

  2. luoguP2444_[POI2000]病毒

    题意 给定多个01模式串,问是否存在一个无限长的字符串不包含任何一个模式串. 分析 好像数据有点水,网上一大堆题解连样例都没过??? 多模式串,先把AC自动机建出来再说. 反向考虑,若存在一个无限长的 ...

  3. Python 标识符说明

    在Python中,标识符有字母.数字.下划线组成 所有标识符都可以包括英文.数字.下划线,但不能以数字开头 Python标识符区分大小写 ※以下划线开头的标识符有特殊含义. 例如:以单下划线开头(_t ...

  4. jmeter+WebDriver:启动浏览器进行web自动化

    无论是web自动化还是手机app自动化,WebDriver是Selenium的核心模块,jmeter WebDriver 仅支持Firefox.Chrome 和 HTML Unit驱动,暂不支持IE  ...

  5. vue项目中引入Sass

    Sass作为目前成熟,稳定,强大的css扩展语言,让越来越多的前端工程师喜欢上它.下面介绍了如何在vue项目 中引入Sass. 首先在项目文件夹执行命令 npm install vue-cli -g, ...

  6. (一)配置linux环境实现持续集成

    目录 1.Centos7操作系统 2.Gnome 可视化桌面 3.远程shell工具 4.远程桌面工具 5.Jdk 6..Net Core 7.Git 8.Docker 容器 9.Kubernetes ...

  7. 业务代码的救星——Java 对象转换框架 MapStruct 妙用

    简介 在业务项目的开发中,我们经常需要将 Java 对象进行转换,比如从将外部微服务得到的对象转换为本域的业务对象 domain object,将 domain object 转为数据持久层的 dat ...

  8. [python]通过微信公众号“Python程序员”,编写python代码

    今天发现微信公众号中,居然可以编写python代码,很是惊喜,觉得蛮有趣的. 步骤如下: 1.关注微信公众号“Python程序员” 2.关注成功后,点击右下角的“潘多拉”->"Pyth ...

  9. P2564 [SCOI2009]生日礼物 贪心

    https://www.luogu.org/problemnew/show/P2564) 题意 有n个珠子,包括k中颜色,找出长度最小的一个区间,使得这个区间中包含所有的颜色. 思路 把n个珠子按照位 ...

  10. Educational Codeforces Round 48 D Vasya And The Matrix

    EDU #48 D 题意:给定一个矩阵,已知每一行和每一列上数字的异或和,问矩阵上的数字是多少,不存在则输出NO. 思路:构造题,可以考虑只填最后一行,和最后一列,其中(n,m)要特判一下.其他格子给 ...