1. 分代收集(Eden, Survivor0, Survivor1, Tenured按内存整块划分,连续的内存地址)
内存默认分配:
young: 1/3
Eden: 8/10
S0:1/10
S1:1/10
old: 2/3
cms:
初始标记(CMS-initial-mark) ,会导致stw;
并发标记(CMS-concurrent-mark),与用户线程同时运行;
预清理(CMS-concurrent-preclean),与用户线程同时运行;
可被终止的预清理(CMS-concurrent-abortable-preclean) 与用户线程同时运行;
重新标记(CMS-remark) ,会导致swt;
并发清除(CMS-concurrent-sweep),与用户线程同时运行;
2. 非分代收集(各个分区不是整块连续,非连续内存地址)
G1两种GC:YoungGC、MixedGC,MixedGC之前会触发YoungGC;
2.1 分区介绍:
内存分为年轻代和老年代,年轻代还是Eden和S0+S1,老年代是Old和Humongous,默认会分2048个内存段,可以分别是不同的代,Humongous存大对象,
如果对象大于内存段的一半,会分配到Humongous上,超过一个大小会分配到连续的Humongous上,也会优先被回收;
2.2 概念介绍
Card Table:
Remembered Set: 每个内存段都对应一个RS,记住谁引用了我,指向card table中对应的entry,垃圾回收时能直接找到对应引用,不用扫描整个堆,
年轻代段内只保存老年代的引用,因为youngGC时会扫描所有年轻代对象,同时发现其引用关系,老年代只保存老年代对象引用,
老年代GC时Eden肯定是空的,都转移到S区了,G1会去扫描Survivor区,S区都是存的老年代的引用,能够获取到和老年代的引用关系,因此老年代只保存自己
就够了;
主要作用:回收单个内存段时,避免对整个堆的所有对象扫描,查看是否有引用;
2.3 回收过程:
不断新建对象到Eden区,Eden区满后触发YoungGC,只回收Eden和Survivor
2.3.1 YoungGC:
1.G1 Stop-the-word
2.创建CS:回收集Collection Set(CS),需要被回收的内存分段集合
3.扫描 GCRoot:
4.更新RS:处理dirty card queue 中的card,更新RS,这时RS能够准确反应老年代对内存段中对象的引用情况
5.处理RS:标记这些被老年代引用的对象,认为是存活对象
6.复制对象:存活对象Eden到Survivor的过程,S区活的对象年龄+1
7.处理引用
2.3.2 老年代并发标记
整个堆内存占用达到一定时(默认45%),会启动老年代回收;检测堆内存使用情况的时机是YoungGC后,或者Humongous对象分配之后;被标记过的对象
引用改为null后,之前的对象会保存到一个队列中
1。YoungGC Stop-the-word,回收后恢复应用线程
2。开始老年代标记,并发进行
3。重新标记 stop-the-world,重新标记队列中的对象
4。回收百分之百为垃圾的内存分段,完成后恢复应用线程
2.3.2 MixedGC
过程同YoungGC,新生代和老年代同时回收,部分为垃圾的内存分段被计算出来,垃圾占比的分段比例越高回收的优先级越高,默认达到65%会被参与回收,老年代内存默认分
8次回收;
2.4 Full GC
触发条件:G1回收过程中,堆内存太小导致复制的对象无空的内存段可分配
网友评论