JavaGC学习笔记
1.简介
Java在JVM虚拟机上的垃圾回收(GC)机制,在合适的时间触发垃圾回收,将不需要的内存空间回收释放,避免无限制的内存增长导致的OOM。
1.1 Java堆内存结构
Java将堆内存分为3大部分:年轻代、老年代和永久代。其中年轻代又进一步划分为Eden、S0、S1(Survivor)三个区。
结构如下图所示:
2、清理算法
A. 年轻代:复制算法
B. 老年代:标记-清除算法 & 标记-整理算法
2.1复制算法:
思路就是把把空间分两部分,一块(A0)用完了,把还活着的对象复制到另外一块(A1),再删除(A0),之后的new的对象都放到A1,当A1满的时候,在把A1活着对象复制到A0,删除A1…….一直循环
因为大部分的对象生命都很短。所以年轻代内存空间划分成一块较大的Eden区和两块较小的Survivor区,两块Survivor区域的大小保持一致。
1、新new的对象,放入Eden+S0
2、Eden+S0满了,把活着的对象复制到S1,删除Eden+S0
3、新new的对象,放入Eden+S1
4、循环….
默认Eden和Survivor的大小比例是8:1:1,也就是说新生代中牺牲掉10%的空间而不是一半的空间。
2.2标记-清除算法
2.3标记-整理算法
3垃圾收集器
3.1收集器介绍
年轻代域:
1、Serial:默认的年轻代收集器,单线程、复制算法实现,回收时挂起所有线程,造成应用停顿
2、ParNew:多线程、复制算法实现,回收时挂起所有线程,造成应用停顿
3、Parallel Scavenge:多线程、复制算法来进行垃圾回收。收集器关注的是吞吐量,即使得应用能够充分使用CPU。
老年代:
1、Serial Old:默认的老年代收集器,采用单线程和标记-整理算法来实现垃圾回收。
2、Parallel Old:Parallel Scavenge收集器的老年代版本,采用多线程和标记-整理算法来实现老年代的垃圾回收。
3、CMS:收集器是一款真正实现了并发收集的老年代收集器, CMS收集器可以最大程度地减少因垃圾回收而造成应用停顿的时间
配合使用关系如下:
3.2 使用收集器
-XX:+UseSerialGC虚拟机运行在client模式下的默认值,使用这个参数表示虚拟机将使用Serial + Serial Old收集器组合进行垃圾回收。
(-XX:+UseSerialGC表示使用这个设置,而-XX:-UseSerialGC表示禁用这个设置。)
-XX:+UseParNewGC使用这个设置以后,虚拟机将使用ParNew + Serial Old收集器组合进行垃圾回收。
-XX:+UseConcMarkSweepGC使用这个设置以后,虚拟机将使用ParNew + CMS + Serial Old的收集器组合进行垃圾回收。注意Serial Old收集器将作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器来进行回收(将会整理内存碎片)。
-XX:+UseParallelGC虚拟机运行在server模式下的默认值。使用这个设置,虚拟机将使用Parallel Scavenge + Serial Old(PS MarkSweep)的收集器组合进行垃圾回收。
-XX:+UseParallelOldGC使用这个设置以后,虚拟机将使用Parallel Scavengen + Parallel Old的收集器组合进行垃圾回收。
3.3 GC日志格式
<datestamp>:[GC[<collector>:<start occupancy1>-><end occupancy1>(total size1),<pause time1> secs]<start occupancy2>-><end occupancy2>(total size2),<pause time2> secs] [Times:<user time> <system time>, <real time>]
datestamp : 表示GC日志产生的时间点,如果指定的jvm参数是-XX:+PrintGCTimeStamps,那么输出的是相对于虚拟机启动时间的时间戳,如果指定的是-XX:+PrintGCDateStamps,那么输出的是具体的时间格式,可读性更高
GC : 表示发生GC的类型,有GC(代表MinorGC)和FullGC两种情况
collector : 表示GC收集器类型,取值可能是DefNew、ParNew、PSYoungGen、Tenured、ParOldGen、PSPermGen等等
start occupancy1 : 表示发生回收之前占用的内存空间
end occupancy1 : 表示发生回收以后还占用的内存空间
total size1 : 该堆区域所拥有的总内存空间
pause time1 : 发生垃圾收集的时间
start occupancy2 : 表示回收前Java堆内存总占用空间
end occupancy2 : 表示回收后Java堆内存还占用的总空间
total size2 : 表示Java堆内存总空间
pause time2 : 表示整个堆回收消耗时间
3.4 收集器逻辑
3.4.1 CMS收集器
3.4.1.1 CMS逻辑介绍
(1) 初始化标记 (inital mark)
这个阶段仅仅是标记了GC Roots能够直接关联到的对象,速度很快,所以基本上感受不到STW带来的停顿。
(2) 并发标记 (concurrent mark)
并发标记阶段完成的任务是从第一阶段收集到的对象引用开始,遍历所有其他的对象引用,并标记所有需要回收的对象。这个阶段,收集线程与用户线程并发交替执行,不必挂起用户线程,所以并不会造成应用停顿。
(3) 并发预清除 (concurrent-pre-clean)
并发预清除阶段是为了下一个阶段做准备,为的是尽量减少应用停顿的时间。
(4) 重新标记 (remark)
这个阶段将会修正并发标记期间因为用户程序继续运作而导致标记产生变动的那部分对象的标记记录(有可能对象重新被引用或者新对象可以被回收)。这个阶段的停顿时间比初始标记阶段要长一些,但是远比并发标记的时间短。
(5) 并发清除 (concurrent sweep)
这个阶段将真正执行垃圾回收,将那些不被使用的对象内存回收掉。
(6) 并发重置 (concurrent reset)
收集器做一些收尾的工作,以便下一次GC周期能有一个干净的状态。
3.4.1.2 CMS日志分析
1,当cms gc开始;CMS-initial-mark:31745K(32768K),指标记时,old代的已用空间和总空间
2,CMS-concurrent-mark,此阶段是和应用线程并发执行的,所谓并发收集器指的就是这个,主要作用是标记可达的对象。
3,CMS-concurrent-preclean,此阶段主要是进行一些预清理,因为标记和应用线程是并发执行的,因此会有些对象的状态在标记后会改变,此阶段正是解决这个问题因为之后的Rescan阶段也会stop the world,为了使暂停的时间尽可能的小,也需要preclean阶段先做一部分工作以节省时间
4,CMS-concurrent-abortable-preclean阶段,加入此阶段的目的是使cms gc更加可控一些,作用也是执行一些预清理,以减少Rescan阶段造成应用暂停的时间
5,再下一个阶段是第二个stop the world阶段了,即Rescan阶段,此阶段暂停应用线程,对对象进行重新扫描并标记;
YG occupancy:964861K(2403008K),指执行时young代的情况
CMS remark:961330K(1572864K),指执行时old代的情况
此外,还打印出了弱引用处理、类卸载等过程的耗时
6,再下一个阶段是CMS-concurrent-sweep,进行并发的垃圾清理
7,最后是CMS-concurrent-reset,为下一次cms gc重置相关数据结构
3.4.1.3 cms常见错误
Concurrent Mode Failure:一个是在年老代被用完之前不能完成对无引用对象的回收;一个是当新空间分配请求在年老代的剩余空间中得到满足
方法一:是降低触发CMS的阀值-XX:CMSInitiatingOccupancyFraction;
方法二:减少年轻代大小,避免放入年老代时需要分配大的空间。
promotion failed:进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代也放不下造成的;
3.4.2 G1
待补充
3.4.3 UseSerialGC
待补充
3.4.4 其他
待补充
4 JVM调优
1、堆大小设置
2、回收器选择
3、辅助信息
4.1 堆内存相关
-Xms用于指定Java应用使用的最小堆内存,如-Xms1024m表示将Java应用最小堆设置为1024M。
-Xmx用于指定Java应用使用的最大堆内存,如-Xmx1024m表示将Java应用最大堆设置为1024m。过小的堆内存可能会造成程序抛出OOM异常,所以正常发布的应用应该明确指定这两个参数。并且,一般会选择将-Xms与-Xmx设置成一样大小,防止JVM动态调整堆内存容量对程序造成性能影响。
-Xmn可以设置堆内存中年轻代的容量,以此达到间接控制老年代容量的作用,因为没有JVM参数可以直接控制老年代的容量。如-Xmn256m表示将年轻代容量设置为256M。假如这个时候额外指定了-Xms1024m -Xmx1024m,那么老年代的容量为768M(1024-256=768)。
-XX:NewRatio=1 可以控制年轻代和老年代的比例
-XX:SurvivorRatio这个参数用于设置新生代中Eden区和Survivor(S0、S1)的容量比值。默认设置为-XX:SurvivorRatio=8表示Eden区与Survivor的容量比例为8:1:1。
4.2 收集器配置
-XX:PretenureSizeThreshold设置直接晋升到老年代的对象大小,大于这个参数的对象将直接在老年代分配,而不是在新生代分配。注意这个值只能设置为字节,如-XX:PretenureSizeThreshold=3145728表示超过3M的对象将直接在老年代分配。
-XX:MaxTenuringThreshold设置晋升到老年代的对象年龄。每个对象在坚持过一次Minor GC之后,年龄就会加1,当超过这个值时就进入老年代。默认设置为-XX:MaxTenuringThreshold=15。
-XX:ParellelGCThreads设置并行GC时进行内存回收的线程数。只有当采用的垃圾回收器是采用多线程模式,包括ParNew、Parallel Scavenge、Parallel Old、CMS,这个参数的设置才会有效。
-XX:CMSInitiatingOccupancyFraction设置CMS收集器在老年代空间被使用多少(百分比)后触发垃圾收集。默认设置-XX:CMSInitiatingOccupancyFraction=68表示老年代空间使用比例达到68%时触发CMS垃圾收集。仅当老年代收集器设置为CMS时候这个参数才有效。
-XX:+UseCMSCompactAtFullCollection设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅当老年代收集器设置为CMS时候这个参数才有效。
-XX:CMSFullGCsBeforeCompaction设置CMS收集器在进行多少次垃圾收集后再进行一次内存碎片整理。如设置-XX:CMSFullGCsBeforeCompaction=2表示CMS收集器进行了2次垃圾收集之后,进行一次内存碎片整理。仅当老年代收集器设置为CMS时候这个参数才有效。
4.3 GC日志相关
-XX:+PrintGCDetails表示输出GC的详细情况。
-XX:+PrintGCDateStamps指定输出GC时的时间格式,比指定-XX:+PrintGCTimeStamps可读性更高。
-Xloggc指定gc日志的存放位置。如-Xloggc:/var/log/myapp-gc.log表示将gc日志保存在磁盘/var/log/目录,文件名为myapp-gc.log。
JavaGC学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...
随机推荐
- 一个box四周边框阴影
实现效果如图: 代码如下: .section { margin: 20upx 30upx; padding: 40upx; border-radius: 6px; border-top: #0670C ...
- oslo_db使用
oslo_db是openstak中封装数据库访问sqlachmy的模块,网上搜索的资源并不多,除了openstack官方文档,在实际使用中的例子凤毛麟角. 有感于资源太少,在学习heat源码的过程中, ...
- Linux 内核态 用户态
内核态和用户态最主要区别在于权限不同,比如特权级别0-3,0级就意味着进入内核态,分级别之后,应该程序大部分情况下运行在用户态,保证了程序运行的安全性 什么情况下会发生从用户态向内核态切换.这里细分为 ...
- CodeWarrior 10 自定义关键字模版
==============================================版本信息开始============================================ 相关作 ...
- Python开发【初始篇】:Linux下安装Python3
Linux系统默认自带python2.6的版本,这个版本被系统很多程序所依赖,所以建议不要轻易删除,除非你能解决其他程序的依赖问题.如果使用最新的Python3需要进行编译安装源码包,这样就对系统默认 ...
- php使用redis的有序集合zset实现延迟队列
延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息. 延迟队列的应用场景: 1.新用户注册,10分钟后发送邮件或站内信. 2.用户下单后,30分钟未支付,订单自动作废. 我 ...
- JavaScript获取扫码枪相关资料
https://blog.csdn.net/jiongxian1/article/details/78906124 https://blog.csdn.net/jifengdalu/article/d ...
- js实现动态加载脚本的方法实例汇总
本文实例讲述了js实现动态加载脚本的方法.分享给大家供大家参考,具体如下: 最近公司的前端地图产品需要做一下模块划分,希望用户用到哪一块的功能再加载哪一块的模块,这样可以提高用户体验. 所以到处查 ...
- mysql 聚集索引和非聚集索引问题(整理)
mysql的聚集索引和非聚集索引 前几天做了一个面试,从优化数据库谈到索引,最后问了我聚集索引和非聚集索引的问题.当时那个叫悔恨啊,平时学习mysql索引这方便的知识,也都看到了这样的字眼,,但总的来 ...
- jQuery的1.x版本的$(element).css()设置元素字体颜色时出现的问题(在IE8以下)
最近赶项目,自己写了个基于jQuery的弹出层插件,中间遇到一个问题,怎么也找不到解决方法,最后发现就是空格的问题...欲哭无泪啊... 在给函数传参时,因为写css代码时习惯在:后面加个空格在写样式 ...