JVM原理与深度调优(三)
jvm垃圾收集算法
1、引用计数算法
每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。还有一个问题是如何解决精准计数。
这种方法现在已经不用了
2、根搜索算法
从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。
在java语言中,GC Roots包括:
虚拟机栈中引用的对象。
方法区中类静态属性实体引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI引用的对象。
jvm垃圾回收算法
1、复制算法(Copying)
- 复制算法采用从根集合扫描,并将存活对象复制到一块新的,没有使用过的空间中,这种算法当控件存活的对象比较少时,极为高效,但是带来的成本是需要一块内存交换空间用于进行对象的移动。
- 此算法用于新生代内存回收,从E区回收到S0或者S1
从根集合扫描、就是刚才说的GC-Roots 收集算法、从它开始查你的引用、如果没有被引用、开始执行算法、并将存活对象复制到一块新的、(S0或者S1)
2、标记清除算法
- 标记-清除算法采用从根集合进行扫描,对存活的对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,如图所示。
- 标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片!
适合老生代去回收
标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。
标记-整理算法是在标记清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。
名词解释
1、串行回收
gc单线程内存回收、会暂停使有用户线程
2、并行回收
收集是指多个GC线程并行工作,但此时用户线程是暂停的;所以,Seral是串行的,Paralle收集器是并行的,而CMS收集器是并发的。
3、并发回收
是指用户线程与GC线程同时执行(不一定是并行,可能交替,但总体上是在同时执行的),不需要停顿用户线程(其实在CMS中用户线程还是需要停顿的,只是非常短,GC线程在另一个CPU上执行)
串行回收要区分好并行回收和并发回收的区别,这地方非常关键、在选择GC的过程中根据应用场景来选择
JVM常见垃圾回收器
上图是HotSpot里的收集器,中间的横线表示分代,有连线表示可以组合使用。
年轻代区域有
Serial 串行
ParNew 并发
Parallel Scavenge 并行
年老代区域有
CMS
Serial Old
Parallel Old
G1目前还不成熟 、适合年轻代和年老代
Serial 回收器(串行回收器)
是一个单线程的收集器,只能使用一个CPU或一条线程区完成垃圾收集;在进行垃圾收集时,必须暂停所有其它工作线程,直到收集完成。
缺点:Stop-The-World
优势:简单。对于单CPU的情况,由于没有多线程交互开销,反而可以更高效。是Client模式下默认的新生代收集器。
新生代Serial回收器
1、通过-XX:+UseSerialGC来开启
Serial New+Serial Old的收集器组合进行内存回收
2、使用复制算法。
3、独占式的垃圾回收。
一个线程进行GC,串行。其它工作线程暂停。
老年代Serial回收器
1、-XX:UseSerialGC来开启
Serial New+Serial Old的收集器组合进行内存回收
2、使用标记-压缩算法
3、串行的、独占式的垃圾回收器。
因为内存比较大的原因,回收比新生代慢
ParNew回收器(并行回收器)
并行回收器也是独占式的回收器,在收集过程中,应用程序会全部暂停。但由于并行回收器使用多线程进行垃圾回收,因此,在并发能力比较强的CPU上,它产生的停顿时间要短
于串行回收器,而在单CPU或者并发能力较弱的系统中,并行回收器的效果不会比串行回收器好,由于多线程的压力,它的实际表现很可能比串行回收器差。
新生代ParNew回收器
1、-XX:+UseParNewGC开启
新生代使用并行回收收集器,老年代使用串行收集器
2、-XX:ParallelGCThreads 指定线程数
默认最好与CPU数理相当,避免过多的线程数影响垃圾收集性能
3、使用复制算法。
4、并行的、独占式的垃圾回收器。
新生代Parallel Scavenge回收器
1、吞吐量优先回收器
关注CPU吞吐量,即运行用户代码的时间/总时间。比如:JVM运行100分钟,其中运行用户代码99分钟,垃圾回收1分钟。则吞吐量是99%,这种收集器能最高效率的利用CPU,适合运行后台运算
2、-XX:+UseParallelGC开启
使用Parallel Scavenge+Serial Old收集器组合回收垃圾,这也是Server模式下的默认值
3、-XX:GCTimeRation
来设置用户执行时间占总时间的比例,默认99,即1%的时间用来进行垃圾回收
4、-XX:MaxGCPauseMillis
设置GC的最大停顿时间
5、使用复制算法
老生代Parallel Old回收器
1、-XX:+UseParallelOldGC开启
使用Parallel Scavenge +Parallel Old组合收集器进行收集
2、使用标记整理算法。
3、并行的、独占式的垃圾回收器。
CMS(并发标记清除)回收器
运作过程分为4个阶段:
初始标记(CMS inital mark):值标记GC Roots能直接关联到的对象。
并发标记(CMS concurrent mark):进行GC RootsTracing的过程。
重新标记(CMS remark):修正并发标记期间用户程序继续运行而导致标记发生改变的那一部分对象的标记.
并发清除(CMS concurrent sweep):
其中标记和重新标记两个阶段仍然需要Stop-The-World,整个过程中耗时最长的并发标记和并发清除过程中收集器都可以和用户线程一起工作
CMS(并发标记清除)回收器
1、标记-清除算法
同时它又是一个使用多线程并发回收的垃圾收集器
2、-XX:ParalleCMSThreads
手工设定CMS的线程数量,CMS默认启动的线程数是(ParallelGCTherads+3)+3/4)
这是它的公式,一般情况下、对于IO密集型的 cpu的核数乘以2+1 ,CPU密集型的一般CPU的核数+1
3、-XX+UseConcMarkSweepGC开启
使用ParNew+CMS+Serial Old的收集器组合进行内存回收,Serial Old作为CMS出现“Concurrent Mode Failure” 失败后的后备收集器使用.
失败以后就会触发Full GC 、位了避免这种情况发生、就要对它进行配置、触发Full GC有两种情况、promotion failed和concurrent mode failure
对于采用CMS进行老年代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent mode failure两种状况,当这两种状况出现时可能
会触发Full GC。
promotion failed是在进行Minor GC时,survivor space放不下、对象只能放入老年代,而此时老年代也放不下造成的;concurrent mode failure是在
执行CMS GC的过程中同时有对象要放入老年代,而此时老年代空间不足造成的(有时候“空间不足”是CMS GC时当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)。
对应措施为:增大survivor space、老年代空间或调低触发并发GC的比率。
4、-XX:CMSInitiatingOccupancyFraction
设置CMS收集器在老年代空间被使用多少后触发垃圾回收器,默认值为68%,仅在CMS收集器时有效,-XX:CMSInitiatingOccupancyFraction=70
(一般情况为70%,设太高了可能会出现失败,设太低了、频繁, 只能去找一个比值、可以分析GC log、看是否符合你的要求 )
5、-XX:+UseCMSCompactAtFullCollection
由于CMS收集器会产生碎片,此参数设置在垃圾收集器后是否需要一次内存碎片整理过程,仅在CMS收集器时有效
6、-XX:+CMSFullGCBeforeCompaction
设置CMS收集器在进行若干次垃圾收集后再进行一次内存碎片整理过程,通常与UseCMSCompactAtFullCollection参数一起使用
7、-XX:CMSInitiatingPermOccupancyFraction
设置Perm Gen使用到达多少比率时触发,默认92%
JVM原理与深度调优(三)的更多相关文章
- JVM原理以及深度调优(二)
JVM内存分配 内存分配其实真正来讲是有三种的.但对于JVM来说只有两种 栈内存分配: 大家在调优的过程中会发现有个参数是-Xss 默认是1m,这个内存是栈内存分配, 在工作中会发现栈OutOfMem ...
- JVM原理与深度调优(一)
什么是jvm jvm是java虚拟机 运行在用户态.通过应用程序实现java代码跨平台.与平台无关.实际上是"一次编译,到处执行" 1.从微观来说编译出来的是字节码!去到哪个平台都 ...
- JVM原理与深度调优
什么是jvm jvm是java虚拟机 运行在用户态.通过应用程序实现java代码跨平台.与平台无关.实际上是"一次编译,到处执行" 1.从微观来说编译出来的是字节码!去到哪个平台都 ...
- (转)JVM原理讲解和调优
背景:jvm实际调优在面试时候经常被问到,所以有必要认真总结一番. 转自:JVM原理讲解和调优 四.JVM内存调优 首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存 ...
- JVM原理讲解和调优
一.什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现 ...
- Jvm原理剖析与调优之内存结构
一些不得不说的概念 JVM JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机包括一套字节码指令集.一组寄存器.一个栈.一个 ...
- java JVM原理讲解和调优和gc
- 深入理解JVM虚拟机10:JVM常用参数以及调优实践
转自http://www.rowkey.me/blog/2016/11/02/java-profile/?hmsr=toutiao.io&utm_medium=toutiao.io&u ...
- JVM基本配置与调优
JVM基本配置与调优 JVM调优,一般都是针对堆内存配置调优. 如图:堆内存分新生代和老年代,新生代又划分为eden区.from区.to区. 一.区域释义 JVM内存模型,堆内存代划分为新生代和老年代 ...
随机推荐
- Shell 命令 之linux 模式下的编程语言
今天简单介绍一下shell 命令的使用,希望对大家有所帮助!!! 一. 1.首先创建一个文本 在终端 touch test.sh 用gedit test.sh 打开.sh 文件 输入如下,第一行是申明 ...
- Redis对象——哈希(Hash)
哈希在很多编程语言中都有着很广泛的应用,而在Redis中也是如此,在redis中,哈希类型是指Redis键值对中的值本身又是一个键值对结构,形如value=[{field1,value1},...{f ...
- Bitmap之位图采样和内存计算详解
原文首发于微信公众号:躬行之(jzman-blog) Android 开发中经常考虑的一个问题就是 OOM(Out Of Memory),也就是内存溢出,一方面大量加载图片时有可能出现 OOM, 通过 ...
- 1000行MySQL学习笔记,不怕你不会,就怕你不学!
Windows服务 -- 启动MySQL net start mysql-- 创建Windows服务 sc create mysql binPath= mysqld_bin_path(注意:等号与值之
- Win32程序:与"LPCWSTR"类型的形参不兼容
出现该问题的原因是通常手动输入的字符串都是LPCSTR类型的, 解决办法如下: 在工程处右键,属性-常规-字符集,将Unicode字符集改为为多字节字符集,应用并确认即可. 字符串常量报错: 在常 ...
- 少儿编程Scratch第一讲:Scratch完美的初体验
素材及视频下载 链接:https://pan.baidu.com/s/1qX0T2B_zczcLaCCpiRrsnA提取码:xfp8 都说未来是人工智能.计算机程式控制的时代,如何让青少年接触计算机编 ...
- Docker的简介以及Dockerfile编写与使用
Docker的简介 Docker是在容器的基础上,进行了进一步的封装,极大的简化了容器的创建和维护.使得Docker技术比虚拟机技术更为轻便.快捷. 下面是两张对比图. 可以看到传统虚拟机技术是虚拟出 ...
- python通过pymysql实现数据库的增删改查
今天实现了python对于数据库的增删改查工作: 具体的每一步的数据库的增删盖茶自己都实验过了. 掌握了基本的数据库操作语言.然后就是对于tuple()的认识. 以及对于查询语句中的:fetchone ...
- MySQL入门,第七部分,单表查询
首先我们需要了解一下整个数据库的结构 其中Student表中Sno为主键.Study表中Sno和Cno合起来做主键.Course表中Cno为主键 其创建脚本如下: #----------------- ...
- C#使用HTML文件中的file文件上传,用C#代码接收上传文件
单独做图片上传很简单,如果要客户端要上传头像保存到服务器就要稍微麻烦一点点了. 不多说了,直接上源码: private void Upload() { string jsonInfo = string ...