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内存模型,堆内存代划分为新生代和老年代 ...
随机推荐
- 6.Metasploit生成apk攻击Android实例
Metasploit进阶第四讲 生成Android apk文件 01 msfvenom基本参数 msfvenom介绍 承接上回,staged/unstage payload如何利用? msfven ...
- Elasticsearch7.6学习笔记1 Getting start with Elasticsearch
Elasticsearch7.6学习笔记1 Getting start with Elasticsearch 前言 权威指南中文只有2.x, 但现在es已经到7.6. 就安装最新的来学下. 安装 这里 ...
- 类实例调用静态方法(Java)
前言 第一次看到在Java中是可以通过类实例调用静态方法,当然不推荐这么做,接下来会讲到,但是在C#中通过类实例调用静态方法在编译时就不会通过,这里做下记录. 类实例调用静态方法 首先我们来看一个简单 ...
- 关于git你日常工作中会用到的一些东西
前言 git是一个版本控制工具, 版本控制主要的好处有三点: 从当前版本回退到任意版本 查看历史版本 对比两个版本差异 git 相关术语 repository 仓库 branch 分支 summary ...
- 为什么要用内插字符串代替string.format
知道为什么要用内插字符串,只有踩过坑的人才能明白,如果你曾今使用string.format超5个以上占位符,那其中的痛苦我想你肯定是能够共鸣的. 一:痛苦经历 先上一段曾今写过的一段代码,大家来体会一 ...
- CPU、内存、硬盘、指令之间的关系
我们都知道所有的程序最终都是一系列计算机能够识别的指令和数据,通过执行这些指令来控制整个计算机. 而CPU就是负责读取和解释执行这些指令的,CPU主要包括运算器.控制器和寄存器,控制器负责把指令.数据 ...
- Y分形的平面微带天线生成过程
Y分形的平面微带天线生成过程 本文介绍了使用Altium Designer脚本程序生成Y型天线的过程,在窗体中线宽.迭代次数,边框长度可以直接设置. Y分形天线用户界面由一个窗体.1个TImage控件 ...
- 【BIM】BIMFACE中创建疏散效果
背景 在BIM运维中,消防疏散是不可或缺的一环,当发生火警的时候,触发烟感器发生报警,同时启动消防疏散,指导现场工作人员进行疏散,及时准确地显示出疏散路线对争取疏散时间尤为重要.我将介绍如何在bimf ...
- python爬虫两个影院的实例
主要两个的python代码如下: import requests from bs4 import BeautifulSoup url = 'https://www.17k.com/' headers ...
- 听说你想要部署 Octopress?满足你
Octopress 是一个面向开发者的博客系统,广受程序员的喜爱.既然大家有需求,那么 Octopress 也要安排上~ 云开发(CloudBase)是一款云端一体化的产品方案 ,采用 serverl ...