文档章节

JVM垃圾收集

囚兔
 囚兔
发布于 2016/02/02 14:24
字数 1898
阅读 79
收藏 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
博文 86
码字总数 47164
作品 1
南京
程序员
私信 提问
Java的垃圾回收之算法[转]

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

kext
2012/03/20
0
0
002_JVM内存结构及调优学习

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

英年求肥
2014/11/11
0
0
Java虚拟机监控指标及监控配置

版权声明:本文为博主原创文章,未经博主允许不得转载。欢迎访问我的博客 https://blog.csdn.net/smooth00/article/details/70229653 主要是对Java虚拟机(JVM)的远程监视,如jdk自带的工具j...

smooth00
2017/04/28
0
0
JVM内存模型及垃圾收集策略解析

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

Kerry_Han
2014/10/27
0
0
My java——JVM(垃圾回收)四

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

tngou
2013/03/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《Maven官方文档》-Maven依赖机制简介

《Maven官方文档》-Maven依赖机制简介 原文地址 译者:Tyrian 依赖机制是Maven最为用户熟知的特性之一,同时也是Maven所擅长的领域之一。单个项目的依赖管理并不难, 但是当你面对包含数百个...

tantexian
10分钟前
0
0
基于 Docker 快速部署多需求 Spark 自动化测试环境

引言 在进行数据分析时,Spark 越来越广泛的被使用。在测试需求越来越多、测试用例数量越来越大的情况下,能够根据需求快速自动化部署 Spark 环境、快速完成所有测试越来越重要。 本文基于 ...

呐呐丶嘿
28分钟前
2
0
支付宝APP支付之查看支付宝商户ID

1、登录支付宝蚂蚁金服开放平台 2、查看账号详情,选择合作伙伴管理,账户管理,查看角色身份,此处的PID就是商户ID 3、点击秘钥管理,可查看绑定的相关应用及其APPID等信息

Code辉
31分钟前
2
0
崛起于Springboot2.X之通讯WebSocket(40)

技术简介:Springboot2.0.3+freemaker+websocket 1、添加pom依赖 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-bo......

木九天
39分钟前
1
0
Java常用四大线程池用法以及ThreadPoolExecutor详解

为什么用线程池? 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处-理效率 2.线程并发数量过多,抢占系统资源从而导致阻塞 3.对线程进行一些简单的管理 在Java中...

孟飞阳
41分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部