GC的相关算法与JVM的垃圾收集器

GC的相关算法

  • 分代管理
  • 复制算法
  • 标记清除
  • 标记压缩

JVM垃圾收集器

P242 表11-1 不同类型垃圾回收期比较

  • 串行收集器 Serial。 Serial GC用于新生代,用了复制算法;Serial Old GC作用于老年代,用的是标记-压缩算法。STW
  • 并行收集器 Parallel。Parallel new作用于新生代,使用了复制算法;Parallel old作用于老年代,用了标记-压缩算法。STW。并发收集是准确收集,不会产生浮动垃圾。
  • 并发收集器 Concurrent-Mark-Sweep。老年代垃圾回收器。使用了标记-清除算法。分为初始标记(Initial-Mark,STW)、并发标记(Concurrent-Mark)、再次标记(Remark,STW)、并发清除(Concurrent-Sweep)。CMS因为需要存储代际的引用关系,所以有额外的存储空间的消耗。CMS不是准确收集,会产生浮动垃圾。
  • 垃圾优先收集器 G1。按照分区进行收集,新生代的分区总是会回收,老生代则是并发标记后选择部分回收效果最好的分区。G1分为三种回收方式:新生代回收young、混合回收(mixed,既收集新生代也收集部分老年代)、FUll GC新生代回收仅仅在开始前需要STW。混合回收分成两个阶段:并发标记阶段与垃圾回收阶段。并发标记阶段又分四个步骤:初始标记子阶段(initital-mark)、并发标记子阶段(concurrent-mark)、再标记子阶段(remark,STW)、清理子阶段(cleanup,STW)。因分区设计,G1引用关系的存储占用额外空间的消耗较大。G1不是准确收集,会产生浮动垃圾。

G1基本概念

分区

G1是将内存分成一个个小区域使用。这些区域称之为Heap Region。扩展的有YHR(新生代分区),OHR(老生代分区),HHR(大对象分区)等等

为了达到分配效率与清理效率的平衡,HR的大小有上下限值,即1MB-32MB。结合整个堆空间分为2048个HR,那么通常G1管理的最大的堆是32MB*2048=64G。

新生代大小

用参数设置使得G1能推断出最大值与最小值

涉及的参数有:

  • 新生代最大值MaxNewSize、最小值NewSize、Xmn(等价于MaxNewSize和NewSize,且MaxNewSize=NewSize)
  • NewRatio,如果上条参数设置了,则忽略本参数
  • 如果仅仅设置了NewRatio,则新生代最大值与最小值相同:整个堆空间/(newRatio+1)
  • 如果没有设置最大值和最小值,或者只设置了其中一个,那么G1将根据参数G1MaxNewSizePercent(默认60)和G1NewSizePercent(默认是5)占整个堆空间的比例来计算。

如果G1推断出的新生代的最大值与最小值相等,则说明新生代不会动态变化,不会动态变化则可能导致后续新生代GC时不能满足期望的停顿时间,所以有文章提到G1不建议设置Xmn参数。

相关代码在 share/vm/gc_implementation/g1/g1collectorPolicy.cpp

G1启发式推断新生代大小

G1有一个线程专门抽样处理预测新生代列表的长度应该多大,并动态调整。

何时扩展以及一次扩展多少内存?

参数-XX:GCTimeRatio 表示GC与应用的耗费时间的比,G1默认是9。也就是说GC的耗时与应用耗时占比超过10%时,进行动态扩展。扩展大小的参数是G1ExpandByPercentOfAvailable,同时至少大于1MB,至多不能超过当前已经分配的大小的一倍。

代码在 size_t G1CollectorPolicy::expansion_amount()....

该书在第五章讲refine线程时对此点有更详细的阐述

G1停顿预测模型

比较偏数学 我就很快跳过去了

G1的预测逻辑是基于衰减平均(Decaying Average)和衰减标准差。

卡表和位图

卡表(CardTable)是CMS中中常见概念之一。我理解成分区间对象引用关系的描述 的存放处或者说存放的数据结构。此书也是讲的较为简略,细节可以参见《垃圾回收算法手册:自动内存管理的艺术》

对象头

讲JVM内存模型必讲对象头。可以参见我写的JVM中对象模型及相应名词概念

栈帧、线程等

栈帧可以参见 封亚飞 写的《揭秘Java虚拟机》第七章 Java栈帧,写的更详细。此书只是一笔带过,看了跟没看没啥差别。

G1的对象分配

  • 快速分配与慢速分配
  • 快速分配通过TLAB(Thread Local Allocation Buffer)实现。TLAB自己的分配是CAS操作。TLAB内部给对象分配是无锁的,因为只有自己线程用嘛。
  • TLAB机制或产生内存浪费,因为一个对象不会分配在两个TLAB区域,所以TLAB最末端的尾巴区域可能会残留空着。可以通过TLABRefillWasteFraction参数调整,表示允许产生浪费的比例。默认值是64,即表示1/64空间可以浪费。
  • TLAB大小可以自动调整,但是上限不会超过HR的一半。、
  • 可以使用参数-XX:-ResizeTLAB禁用ResizeTLAB,并使用参数-XX:TLABSize指定一个大小。-XX:+PrintTLAB可以跟踪TLAB工作情况。
  • 一般不建议修改TLAB参数,建议使用默认值

TLAB快速分配的代码在 HeapWord* CollectedHeap::allocate_from_tlab...

G1的Refine线程

先讲Rset

Rset

Rset是干什么用的?

  • Rset是一种抽象概念,记录了在不同代际之间的引用关系,目的是为了加速GC。
  • 通俗地说,可以用Rset记录从非收集部分指向收集部分的指针集合。对于这种记录述求,有两种方式,一是我引用了谁,称为Point Out;一是谁引用了我,称为Point In。G1采用后者。
  • G1中需要记录代际之间的引用关系包括:老生代分区到新生代分区之间的引用关系(YGC时,这个引用关系是GC Roots的一部分,老生代引用过来的不能被回收掉嘛...);老生代分区到老生代分区之间的引用关系(混合GC时用)
  • Rset与卡表的关系参见P68图4-1
  • G1引入了PRT,TODO:没看太懂
  • DCQ与Refinemnet zone的四色区域没看太懂

Rset写屏障

为啥谈到写屏障,因为Refine是线程关注的是应用关系的变更,但是他是如何识别引用关系的变更的呢?就是靠写屏障完成。下面讲写屏障相关要点:

  • 写屏障这个词我不知道为啥这样命名,直觉上不好理解。
  • 我对其的理解就是,写操作前后的拦截器处理。比如我对字段赋值putfield,在赋值前我要告诉DCQ这个对象被我引用了,这就是写屏障动作。
  • 书上的说法:写屏障是指在改变特定内存的值时,额外执行的一些动作。
  • CMS是通过写屏障记录引用刮不洗,G1也是。
  • 写屏障会有优化,不是所有的引用关系变更都会被记录。
    • 不记录新生代到新生代的引用,或者新生代到老生代的引用,在写屏障时过滤
    • 过滤掉同一个分区内部引用,在Rset处理时过滤
    • 过滤掉空引用,在Rset处理时过滤

Refine线程

  • Refine线程是一组,是一个线程池,不是一个。
  • 我对他的理解是,一个线程用于抽样,主要作用设置新生代分区的个数。其余线程用于管理Rset,Rset的更新不是同步完成的,是靠Refine线程异步完成的,异步又是靠DCQ dirty card queue队列暂存过渡的。
  • Refine涉及的JVM比较复杂,未细细研究
  • 相关参数:可以通过-XX:+G1TraceConcRefinement观察Refine线程工作情况。通过-XX:+G1SummarizeRSetStats观察Rset更新。

新生代回收

上面已经讲了,G1 GC分三种: 新生代回收young、混合回收(mixed,既收集新生代也收集部分老年代)、FUll GC

步骤:

  1. 选择CSet
  2. 根处理
  3. Rset处理
  4. 复制
  5. Redirty 重构Rset
  6. 释放空间

相关日志

可以用-XX:G1LogLevel=finest 打开更详细的日志

关键字 GC pause (G1 Evacuation Pause) (young), 0.0182341 secs...

参数调优

混合回收

混合回收分成两个阶段:

  • 并发标记阶段
  • 垃圾回收阶段(与新生代回收一致)

并发标记阶段又分四个步骤:

  1. 初始标记子阶段(initital-mark)
  2. 并发标记子阶段(concurrent-mark)
  3. 再标记子阶段(remark,STW)
  4. 清理子阶段(cleanup,STW

并发标记的难点:

正在标记过程中的对象引用关系发生了改变。

通过三色标记法与STAB算法结合写屏障完成。

写屏障代码在 oop_store中,oop.inline.hpp

相关日志

关键字 GC pause (G1 Evacuation Pause) (mixed), 0.0106341 secs...

GC pause (G1 Evacuation Pause) (young) (initial-mark),.... // 初始标记借用了YGC

[GC concurrent-mark-start]...

[GC concurrent-mark-end]...

[GC remark ...]...

[GC cleanup ...]...

参数调优

Full GC

JDK10之前FGC是串行的,JDK10之后支持并行。

代码在 G1CollectedHeap::do_collection

串行回收采用标记清除算法,步骤:

  1. 标记活跃对象
  2. 计算新对象地址
  3. 把所有对象都更新到新地址上
  4. 移动对象完成压缩

相关日志

[Full GC (Allocation Failure) ..... 0.2036229 secs]....

G1调优

主要涉及的指标有: 吞吐量最大、停段时间尽量端、GC频率尽量低和堆空间的有效利用率高。

主要调优参数 参见P244 表11-2,主要涉及堆、RSet、标记和GC四个方面的参数。

《JVM G1源码分析和调优》读书笔记的更多相关文章

  1. csapp读书笔记-并发编程

    这是基础,理解不能有偏差 如果线程/进程的逻辑控制流在时间上重叠,那么就是并发的.我们可以将并发看成是一种os内核用来运行多个应用程序的实例,但是并发不仅在内核,在应用程序中的角色也很重要. 在应用级 ...

  2. CSAPP 读书笔记 - 2.31练习题

    根据等式(2-14) 假如w = 4 数值范围在-8 ~ 7之间 2^w = 16 x = 5, y = 4的情况下面 x + y = 9 >=2 ^(w-1)  属于第一种情况 sum = x ...

  3. CSAPP读书笔记--第八章 异常控制流

    第八章 异常控制流 2017-11-14 概述 控制转移序列叫做控制流.目前为止,我们学过两种改变控制流的方式: 1)跳转和分支: 2)调用和返回. 但是上面的方法只能控制程序本身,发生以下系统状态的 ...

  4. CSAPP 并发编程读书笔记

    CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...

  5. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  6. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  7. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  8. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  9. C#刨根究底:《你必须知道的.NET》读书笔记系列

    一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...

  10. Web高级征程:《大型网站技术架构》读书笔记系列

    一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...

随机推荐

  1. PyQt5主界面

    QMainWindow QMainWindow控件继承之QWidget控件,QWidget是所有控件的父类,主要提供界面的基本功能,包括边框.标题.工具栏.关闭按钮.最小化按钮以及最大化按钮等.子类中 ...

  2. Redis集群搭建(哨兵)

    最近工作中需要用到redis哨兵集群,笔者自己搭建了3遍,直接开始 环境: 1,系统环境 系统 版本 操作系统 CentOS 7.4 Redis 5.0.8 2,IP请修改成自己的IP redis I ...

  3. windows如何解决Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion'

    问题再现与解读 首次,使用 java 命令+任意参数 都会报这个错误,最典型的就是java -version 解读一下这个报错信息,注册表路径 Software\JavaSoft\Java Runti ...

  4. springboot(二)配置SpringBoot支持自动装载Servlet

    Servlet详解:https://blog.csdn.net/yanmiao0715/article/details/79949911 Web 技术成为当今主流的互联网 Web 应用技术之一,而 S ...

  5. 【NeurlPS2019】Positional Normalization 位置归一化

    作者提出,当前的BatchNorm, GroupNorm, InstanceNorm在空间层面归一化信息,同时丢弃了统计值.作者认为这些统计信息中包含重要的信息,如果有效利用,可以提高GAN和分类网络 ...

  6. 《Python编程初学者指南》高清PDF版|百度网盘免费下载|Python基础

    <Python编程初学者指南>|百度网盘免费下载| 提取码:03b1 内容简介 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.Python可以用于很多的领域,从科学计 ...

  7. mongoose.model第三个参数的问题

    这个是个好问题,之前按照教程做的数据库没有问题,现在自己从新做出现了问题.还好之前有无意中接触了这个知识点,不然感觉真的很难解决. 在检查完所有东西都没错的时候(前端传给req的数据正常,与数据库相符 ...

  8. WPF 半透明 模糊效果 Aero效果(1)

    先看看效果图 目前网上找到了2种实现方式,一种是 .NET Framework4.5及以后有自带的 WindowChrome 效果,一种是 WindowsAPI  dwmapi.dll  ,但这两种在 ...

  9. Workerman学习笔记(一)初步认识

    本文只是概念性的知识,内容比较零散,下篇文章再进行代码分析. Workerman是什么,他的优势在哪? 官方给的解释是高性能socket框架,我的个人理解是实现多进程的通讯的服务框架. 与传统的PHP ...

  10. RESTFUL风格的URL请求及参数接收

    RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义.RESTFUL适用于移动互联网厂商作为业务使能接口的场景,实现第三方OTT调用移动网络资源 ...