文档章节

JVM垃圾收集

囚兔
 囚兔
发布于 2016/02/02 14:24
字数 1898
阅读 71
收藏 1

目录

  1. 内存区域回顾
  2. 机制介绍
  3. 收集器介绍
  4. 调优

内存区域回顾

内存区域

垃圾回收机制

Java 对象生命周期

输入图片说明

根搜索算法

输入图片说明

输入图片说明 从GC Roots对象为起点,开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链时,此对象即为不可用,被判定为可回收对象。

标记过程

输入图片说明

垃圾收集算法

输入图片说明

堆内存区域划分

输入图片说明

垃圾收集器

输入图片说明

Serial - 新生代串行收集器

输入图片说明

  • 使用单线程进行垃圾回收
  • 独占式
  • 优点:实现简单,处理高效
  • 缺点:Stop The World
  • 使用-XX:+UseSerialGC指定使用
  • JVM在Client模式下默认垃圾收集器

ParNew - 新生代并行收集器

输入图片说明

  • 实现和Serial相同,仅将GC线程改成多线程
  • 优点:在多CPU情况下优于Serial
  • 缺点:Stop The World
  • -XX:+UseParNewGC
  • GC线程数,-XX:ParallelGCThreads,
  • 当CPU个数 < 8,ParallelGCThreads=CPU个数
  • 当CPU个数 > 8,ParallelGCThreads=3 + ( (5 * CPU个数) / 8)

Parallel Scavenge - 新生代并行收集器

线程模型和ParNew相同,区别在于Parallel Scavenge收集器的目标是达到一个可以控制的吞吐量

  • -XX:+UseParallelGC,指定使用
  • -XX:MaxGCPauseMillis,设置最大停顿时间,大于0的整数
  • -XX:GCTimeRatio,设置吞吐量大小,0~100整数,即运行用户代码时间 / 垃圾收集时间,默认值为99
  • -XX:+UseAdaptiveSizePolicy 自适应GC策略开关,在自适应模式下,新生代大小,survivor和eden区的比例、晋升老年代对象年龄等参数会被自动调整,以达到最合适的停顿时间,或最大吞吐量。

Serial Old - 老年代串行收集器

  • 使用标记-整理算法
  • 和Serial一样是串行独占式回收器
  • 可和Serial,ParNew 搭配使用
  • 缺点停顿时间可能会比较长

Parallel Old - 老年代并行收集器

  • 使用标记-整理算法
  • 和Parallel Scavenge一样是并行多线程收集器,也是关注于吞吐量
  • -XX:+UseParallelOldGC
  • 缺点停顿时间可能会比较长

CMS - 老年代并发收集器

输入图片说明 全称:Concurrent Mark Sweep

  • 基于标记-清除算法
  • 一种以获取最短停顿时间为目标的收集器

初始标记、重新标记仍然需要“Stop The world”。初始标记只标记GC Roots能直接关联到的对象,速度很快,时间很短。并发标记进行GC Roots Tracing,比较耗时。重新标记修正并发标记期间,程序继续运行导致的标记变动。由于整个过程中耗时最长的并发标记和并发清除阶段,GC线程可以与用户线程一起工作,总体上来说CMS是一款并发收集器,这也是CMS停顿时间较短的原因。

  • -XX:+UseConcMarkSweepGC 新生代使用并行收集器,老年代使用CMS + Serial Old
几个缺点
  • Cpu很敏感,并发阶段默认线程数是(CPU数量+3)/ 4 , CPU不足4个时,对程序性能影响较大
  • 无法处理浮动垃圾,清理阶段,用户线程继续运行会产生新的垃圾,可能出现“Concurrent Mode Failure”失败
  • CMS使用标记-清除算法,会产生大量空间碎片
优化方案
  • -XX:CMSInitiatingOccupancyFraction, 设置CMS收集器老年代使用多少空间会被激活,另外当出现“Concurrent Mode Failure”时,将临时启用Serial Old收集器来重新对老年代进行收集
  • -XX:+UseCMSCompactAtFullCollection, 开关参数,表示每次full GC后执行一次碎片整理。-XX:CMSFullGCsBeforeCompaction, 设置执行多少次full GC后,来一次碎片整理

垃圾收集参数总结

参考:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

两种参数格式:

  • 开关参数,比如 -XX:+UseSerialGC,“+”代表开,“-”代表关
  • 值参数,比如 -XX:ParallelGCThreads=4
串行回收器(Serial + Serial Old)

-XX:+UseSerialGC 在新生代和老年代中使用串行收集器 -XX:SurvivorRatio 设置Eden与Survivor区大小比例 -XX:PretenureSizeThreshold 设置大对象直接进入老年代的阈值

并行GC(ParNew + CMS + Serial Old)
  • -XX:+UseParNewGC 在新生代使用并行收集器,默认老年代使用Serial Old,ParNew + Serial Old 已过期,不再推荐使用
  • -XX:+UseConcMarkSweepGC 新生代使用并行收集器,老年代使用CMS + Serial Old
  • -XX:ParallelGCThreads 设置用于垃圾回收的线程数
  • -XX:CMSInitiatingOccupancyFraction 设置CMS收集器在老年代空间被使用多少后触发, JDK7中默认为92%, CMSInitiatingOccupancyFraction = (100 - MinHeapFreeRatio) + (CMSTriggerRatio * MinHeapFreeRatio / 100)
  • -XX:+UseCMSCompactAtFullCollection 设置CMS收集器在完成垃圾收集后是否进行一次内存碎片整理,默认为true
  • -XX:CMSFullGCsBeforeCompaction 设定多少次CMS垃圾回收后,进行一次内存碎片整理,默认为0
  • -XX:+CMSClassUnloadingEnabled 允许对类元数据进行回收
  • -XX:CMSInitiatingPermOccupancyFraction 当永久代占用率达到这个百分比时,启用CMS回收(前提先开启CMSClassUnloadingEnabled)
并行GC(Parallel Scavenge + Parallel Old)
  • -XX:UseParallelGC 新生代使用Parallel Scavenge,server模式下默认开启
  • -XX:UseParallelOldGC 年老代使用Parallel Old, server模式下默认开启
  • -XX:ParallelGCThreads 设置用于垃圾回收的线程数
  • -XX:MaxGCPauseMillis 设置最大垃圾收集停顿时间
  • -XX:GCTimeRatio 设置吞吐量大小,它的值是一个0~100之间的整数,执行用户代码的时间 / 垃圾收集时间
  • -XX:+UseAdaptiveSizePolicy 打开自适应GC策略
  • -XX:+PrintAdaptiveSizePolicy 打印自适应分代大小调整信息
其他
  • -XX:MaxTenuringThreshold 设置对象进入老年代的年龄最大值,每一次Minor GC后,对象年龄加1,默认值15,使用ConcMarkSweep时默认6
  • -XX:+DisableExplicitGC 禁用显式GC,System.gc() 失效
  • -XX:+PrintGCDetails 显示GC日志详细信息
  • -Xloggc:<filename> 将GC日志输出到日志文件
  • -Xmx 堆最大大小
  • -Xms 堆初始大小
  • -Xmn 新生代大小,相当于NewSize和MaxNewSize固定为相同的值
  • -XX:NewSize 新生代初始大小
  • -XX:MaxNewSize 新生代最大大小
  • -XX:PermSize 永久代初始大小
  • -XX:MaxPermSize 永久代最大大小
  • -XX:+PrintFlagsFinal 打印最终的参数值
  • -XX:+PrintCommandLineFlags

内存分配和回收策略

  • 对象优先在Eden区分配
  • 大对象直接进入老年代, -XX:PretenureSizeThreshold, 设置大对象直接进入老年代的大小阈值。只在Serial GC 和ParNew GC时有效,尽量在程序中避免大对象的存在
  • 长期存活的对象进入老年代, -XX:MaxTenuringThreshold, 对象经历MinorGC的次数,默认为15,不一定非要到达这个年龄才进入老年代。
  • 空间分配担保

调优

GC日志收集参数

  • -verbose:gc
  • -XX:+PrintGCDetails
  • -XX:+PrintGCDateStamps 显示gc日志时间年月日时分秒
  • -XX:+PrintGCTimeStamps 显示gc日志距启动的时长
  • -Xloggc:gcfile
  • -XX:+HeapDumpOnOutOfMemoryError
  • -XX:HeapDumpPath

GC日志解读

输入图片说明 Times: user - 用户态消耗的cpu时间 sys - 内核态消耗的cpu时间 real - 操作从开始到结束经过的墙钟时间

GC日志收集分析工具

  • jmap
  • jstat / jstatd
  • jconsole
  • jVisualVM

上面工具的都包含在jdk bin目录下

  • GCViewer

减少Full GC

  • 将新对象预留在新生代
  1. 增大新生代空间
  2. 增大survivor区大小,-XX:SurvivorRatio,默认值8
  3. 提高from区利用率 -XX:TargetSurvivorRatio, 默认值50
  • 防止永久代满导致full GC
  • 谨慎使用System.gc() // 堆外内存相关, -XX:+DisableExplicitGC --禁用

选择合适的垃圾收集器

吞吐量优先

使用ParallelGC + ParallelOldGC

降低停顿时间

使用ParNewGC + CMS,CMS对老年代的回收暂停时间远远小于ParallelOld

案例

见《jvm调优案例-xwiki吞吐量调优》

© 著作权归作者所有

共有 人打赏支持
囚兔

囚兔

粉丝 38
博文 82
码字总数 46066
作品 1
南京
程序员
My java——JVM(垃圾回收)四

续My java——JVM(内存域) 中讲述了Java在JVM中的内存使用,其实在我们出来java程序时基本上有两个地方的内存处理 一是栈、二是堆,JVM会自动回收堆中的内存,也就我们所说的垃圾回收,那J...

tngou
2013/03/20
0
0
Java的垃圾回收之算法[转]

引言 Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等...

kext
2012/03/20
0
0
《成神之路-基础篇》JVM——垃圾回收(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 ...

05/05
0
0
002_JVM内存结构及调优学习

常遇到关于内存溢出的错误 java.lang包下 StackOverflowError 很少 OutOfMemoryError: heap space(堆空间) 比较常见 OutOfMemoryError: PermGen space 经常出现 2. Java虚拟机结构和属性...

英年求肥
2014/11/11
0
0
JVM内存模型及垃圾收集策略解析

AD: JVM内存模型是Java的核心技术之一,之前51CTO曾为大家介绍过JVM分代垃圾回收策略的基础概念,现在很多编程语言都引入了类似Java JVM的内存模型和垃圾收集器的机制,下面我们将主要针对J...

LEON_SHI
2014/08/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

人生苦短:Python里的17个“超赞操作

人生苦短,我选Python”。那么,你真的掌握了Python吗? 1. 交换变量 有时候,当我们要交换两个变量的值时,一种常规的方法是创建一个临时变量,然后用它来进行交换。比如: # 输入 a = 5 b ...

糖宝lsh
39分钟前
4
0
咕泡-spring中常用设计模式概述

设计模式就是经验之谈,供后人借鉴,解决一些具有代表性的问题 设计模式来源于生活,反过来帮助我们更好生活 设计模式提升代码的可读性、可扩展性、维护成本、复杂业务问题 千万不要死记硬背...

职业搬砖20年
今天
2
0
day59-20180817-流利阅读笔记-待学习

假·照骗,真·社交焦虑 雪梨 2018-08-17 1.今日导读 发朋友圈之前,不少人为了展现更美好的生活状态会对照片加以“微调”,或是加个滤镜显得逼格更高,或是磨个皮瘦个脸拉个大长腿。现在,国...

aibinxiao
今天
19
0
OSChina 周五乱弹 —— 姑娘在这个节日里表白你接受么?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @Sharon啊:完全被这个小姐姐圈粉了,学两首她的歌去哈哈 分享王贰浪的单曲《往后余生(翻自 马良)》 《往后余生(翻自 马良)》- 王贰浪 手...

小小编辑
今天
949
16
为什么HashMap要自己实现writeObject和readObject方法?

为什么HashMap要自己实现writeObject和readObject方法? 如果你有仔细阅读过HashMap的源码,那么你一定注意过一个问题:HashMap中有两个私有方法。 private void writeObject(java.io.Objec...

DemonsI
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部