GC
2020-01-03 09:48:38 2 举报
AI智能生成
JVM 收集算法和垃圾收集器
作者其他创作
大纲/内容
检测对象存活算法
引用计数法
对象每当被引用+1
缺点:无法处理循环引用
可达性分析算法
GC Roots是否可达判定对象是否存活
垃圾收集算法
标记-清除算法(Mark-Sweep)
概念
最基础的收集算法,后续的收集算法可以理解为是该算法的基础上改进的
标记出所有待回收对象,然后统一回收。
执行过程
标记
清除
缺点
效率问题: 标记和清除的过程的效率都不高
产生空间碎片
复制算法(Copying)
概念
将内存分割成两块,每次只使用其中的一块,当一块内存用完了,就将存活的对象复制到另一块上,然后清理内存
使用场景
适用于新生代(Eden、Survivor、Survivor),不适合存活率比较高的老年代
适用于对象存活率低的场景,当需要复制的对象太多时,效率会下降
缺点
需要浪费一定的内存进行分配担保
标记-整理算法
概念
类似标记-清除算法
执行过程
标记
整理
将存活对象移动到一端
清理
清理一端边界意外的内存
适用场景
适用于对象存活率毕竟大的老年代
分代收集算法
概念
当前商业虚拟机的垃圾收集都采用“分代收集算法”
新生代
老年代
垃圾收集器
基本概念
串行
单线程,gc线程与用户线程不能同时执行,Stop The Word
并行
指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
并发
指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。
新生代垃圾收集器
Serial收集器
概念
采用复制算法
单线程的收集器,进行垃圾收集时,必须暂停其他所有的工作线程(Stop The World)
适用场景
对于限定单个CPU的环境来说,Serial收集器没有线程交互(切换)开销,可以获得最高的单线程收集效率;
JVM client模式下默认的新生代收集器
在用户的桌面应用场景中,可用内存一般不大(几十M至一两百M),可以在较短时间内完成垃圾收集(几十MS至一百多MS),只要不频繁发生,这是可以接受的
相关参数
-XX:+UseSerialGC
待总结
ParNew收集器
概念
采用复制算法
Serial的多线程版本
与Serial公用了很多代码
适用场景
ParNew能与CMS收集器配合,Parallel Scavenge 不能CMS配合适用
缺点
单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境中都不能百分之百地保证可以超越Serial收集器
相关参数
-XX:+UseConcMarkSweepGC
指定使用CMS后,会默认使用ParNew作为新生代收集器
-XX:+UseParNewGC
强制指定使用ParNew
-XX:ParallelGCThreads
指定垃圾收集的线程数量,ParNew默认开启的收集线程与CPU的数量相同
图
Parallel Scavenge收集器
概念
采用复制算法
与ParNew 相似也是并行的多线程收集器,更关注吞吐量(其他线程更关注用户线程的停顿时间),又称吞吐量优先收集器
Jdk1.8默认年轻代收集器
支持自适应调节策略,也是与ParNew收集器的一个重要区别
相关参数
-XX:+UseParallelGC
使用的垃圾收集器是:新生代(Parallel Scavenge),老年代(Serial Old(MarkSweep))组合
-XX:MaxGCPauseMillis
控制最大垃圾收集停顿时间,设置大于0的毫秒数
-XX:GCTimeRatio
垃圾收集时间占总时间的比率(直接设置吞吐量大小),设置0~100
-XX:+UseAdaptiveSizePolicy
自适应调节策略
使用场景
主要适合后台运算而不需要太多交互的场景
老年代垃圾收集器
Serial Old收集器
概念
使用“标记-整理”算法
Serial Old是Serial收集器的老年代版本,单线程收集器,jdk1.8默认老年代垃圾收集器
适用场景
JVM Client模式下
单个CPU场景
配合Parallel Scavenge使用
CMS的后备预案
Parallel Old收集器
概念
使用“标记-整理”算法
Parallel Scavenge的老年代版本
使用场景
在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器
CMS收集器
概念
Concurrent Mark Sweep
“标记—清除”算法
是一种以获取最短回收停顿时间为目标的收集器
适用场景
大部分的Java应用集中在互联网站或者B/S系统的服务端上,重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。
运行过程
初始标记
标记一下GC Roots能直接关联到的对象, stop the word
并发标记
进行GCRoots Tracing的过程
重新标记
修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录 stop the word
并发清除
运行过程图
图
优点
并发收集、低停顿
从总体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行
缺点
CMS收集器对CPU资源非常敏感
CMS收集器无法处理浮动垃圾(FloatingGarbage),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生
容易产生大量空间碎片
常用参数
-XX:CMSInitiatingOccupancyFraction
设置CMS收集器的启动阈值
-XX:+UseCMSCompactAtFullCollection
默认开启的,用于在CMS收集器顶不住要进行FullGC时开启内存碎片的合并整理过程,内存整理的过程是无法并发的,空间碎片问题没有了,但停顿时间不得不变长
-XX:CMSFullGCsBeforeCompaction
用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,表示每次进入Full GC时都进行碎片整理)
G1收集器
概念
整体看采用“标记整理算法”;局部看采用复制算法
G1是一款面向服务端应用的垃圾收集器,jdk9的默认收集器,CMS的长期替代者
允许用户设置应用的暂停时间
把内存“化整为零”,它将整个Java堆划分为多个大小相等的独立区域(Region)
不需要其他收集器配合就能独立管理整个GC堆
运行过程
初始标记(Initial Marking)
标记GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这阶段需要停顿线程,但耗时很短
并发标记(Concurrent Marking)
从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行
最终标记(Final Marking)
修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行
筛选回收(Live Data Counting and Evacuation)
对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,与用户程序一起并发执行
流程图
图
特点
并行与并发
G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短Stop-The-World停顿的时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继续执行。
分代收集
与其他收集器一样,分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果
空间整合
与CMS的“标记—清理”算法不同,G1从整体来看是基于“标记—整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
可预测的停顿
这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了
面试题
G1收集器为什么可以做到可预测停顿
G1将内存”化整为零”,将堆区划分为多个大小相等的独立区域(Region)
G1是根据后台维护的一个优先列表和用户配置的应用的暂停时间,优先回收价值最大的Region
而其他垃圾收集器每次回收都会回收整个Generation的内存(Eden, Old), 而回收内存所需的时间就取决于内存的大小,以及实际垃圾的多少,所以垃圾回收时间是不可控的
在G1收集器中,Region之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,虚拟机都是使用Remembered Set来避免全堆扫描的。G1中每个Region都有一个与之对应的Remembered Set,虚拟机发现程序在对Reference类型的数据进行写操作时,会产生一个WriteBarrier暂时中断写操作,检查Reference引用的对象是否处于不同的Region之中(在分代的例子中就是检查是否老年代中的对象引用了新生代中的对象),如果是,便通过CardTable把相关引用信息记录到被引用对象所属的Region的Remembered Set之中。当进行内存回收时,在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏
垃圾收集器关系图
垃圾收集器
常用参数
图
0 条评论
下一页