java架构之路-(12)JVM垃圾回收算法和垃圾回收器
接上次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垃圾回收算法和垃圾回收器的更多相关文章
- java架构之路-(JVM优化与原理)JVM之G1回收器和常见参数配置
过去的几天里,我把JVM内部的垃圾回收算法和垃圾回收器.还剩下最后一个G1回收器没有说,我们今天数一下G1回收器和常见的参数配置. G1回收器 G1 (Garbage-First)是一款面向服务器的垃 ...
- JVM 垃圾回收算法和垃圾回收器
JVM 垃圾回收算法和垃圾回收器. 一.垃圾回收的区域 栈:栈中的生命周期是跟随线程,所以一般不需要关注. 堆:堆中的对象是垃圾回收的重点. 方法区:这一块也会发生垃圾回收,不过这块的效率比较低,一般 ...
- 直通BAT必考题系列:JVM的4种垃圾回收算法、垃圾回收机制与总结
垃圾回收算法 1.标记清除 标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段. 在标记阶段首先通过根节点(GC Roots),标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象. ...
- java中的垃圾回收算法与垃圾回收器
常用的垃圾回收算法 标记-清除 标记清除算法是一种非移动式的回收算法,分为标记 清除 2个阶段,简而言之就是先标记出需要回收的对象,标记完成后再回收掉所有标记的内存对象,如下图 可见回收后图中被标记的 ...
- Java垃圾回收算法和垃圾回收器
基本上 jvm内存回收有三种 基本算法 标记-清除 标记清除的算法最简单,主要是标记出来需要回收的对象,然后然后把这些对象在内存的信息清除.如何标记需要回收的对象,在上一篇文章里面已经有说明. 标记- ...
- java架构之路-(JVM优化与原理)JVM类的加载机制
话不多说,先上图. ***.class文件执行大概就是这样来走的.我们都知道我们的java文件经过编译以后会生成对应的class文件.先经过类装载子系统,然后塞进运行时内存模型的元空间,开始执行方法, ...
- java架构之路-(JVM优化与原理)JVM的运行时内存模型
还是我们上次的图,我们上次大概讲解了类加载子系统的执行过程,验证,准备,解析,初始化四个过程.还有我们的双亲委派机制. 我们这次来说一下运行时内存模型.上一段小代码. public class Mai ...
- Java垃圾回收算法和内存分配策略
垃圾回收算法和内存分配策略 Java垃圾回收 垃圾收集,也就是GC并不是Java的伴生物,而对于GC的所需要完成任务主要就是: 1.哪些内存是需要回收的? 2.何时去回收这些内存? 3.以何种方式去回 ...
- JVM学习总结二——垃圾回收算法
昨天总结了JVM内存分区相关的知识,这次我们将来了解下JVM的另一个核心知识点——垃圾回收算法.这一部分其实并不太难,如果对操作系统的内存处理算法有所了解,那么这部分算法其实只看名字就能明白,两者在原 ...
随机推荐
- (二十三)c#Winform自定义控件-等待窗体
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
- 记基于docker+gunicorn部署sanic项目遇到的很多很多坑
前言: 最近有个项目需要上线,是python中sanic网络异步框架写的,并且要求使用docker+nginx来部署项目实现负载均衡,于是乎百度了sanic项目部署,基本上都是基于docker+gun ...
- 多渠道推广场景下,如何实现 App 用户增长的精准归因?
为了实现用户的快速增长,以推广 App 为目标的线上广告投放是很多平台获取新用户的重要方式.随道移动互联网的发展,现在 App 推广的渠道越来越丰富,除了 WAP 站点.第三方 App 之外,HTML ...
- win7 部署tomcat
1,下载 jdk:http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u3-download-1501626.html 2,下载t ...
- [Python] socket发送UDP广播实现聊天室功能
一.说明 本文主要使用socket.socket发送UDP广播来实现聊天室功能. 重点难点:理解UDP通讯流程.多线程.UDP广播收发等. 测试环境:Win10\Python3.5. 程序基本流程:创 ...
- c++学习笔记_4
前言:本笔记所对应的课程为中国大学mooc中北京大学的程序设计与算法(三)C++面向对象程序设计,主要供自己复习使用,且本笔记建立在会使用c和java的基础上,只针对与c和java的不同来写 运算符重 ...
- 牛客小白月赛4 B 博弈论 思维 字符串
链接:https://www.nowcoder.com/acm/contest/134/B来源:牛客网 题目描述 铁子和顺溜在学习了博弈论的sg函数之后,解决了很多很多博弈题,现在他们遇到了一道难题. ...
- CodeForces Educational Codeforces Round 51 (Rated for Div. 2)
A:Vasya And Password 代码: #include<bits/stdc++.h> using namespace std; #define Fopen freopen(&q ...
- 题解 UVA11000 【Bee】
传送门 [题目描述] 在非洲有一种非常特殊的蜜蜂.每年,这种蜜蜂的一只雌蜂生育一只 雄蜂,而一只雄蜂生育一只雌蜂和一只雄蜂,生育后它们都会死去!现在科学家们意外地发现了这一特殊物种的一只神奇的雌蜂,她 ...
- 解决问题:SpringMvc中转发的html文件中文是乱码
目录 1.环境说明,以及前言 2.问题描述: 3.失败的方法(这里写失败并不代表在其他情况不管用) 3.1 html网页本身编码不是UTF-8(推荐尝试) 3.2 web.xml中没有设置配置编码方式 ...