1.什么是垃圾
没有任何引用指向的一个对象,或多个对象(循环引用)
2.如何定位垃圾
引用计数法(无法解决循环引用)
根可达算法(通过根对象找不到的对象都是垃圾)
根对象:线程栈变量,引入的Class的静态变量,常量池和JNI指针引用到的变量
3.常见的垃圾回收算法
Mark-Sweep(标记清除):位置不连续 产生碎片 效率偏低(两遍扫描)
Copying(拷贝):没有碎片,浪费空间
Mark-Compact(标记压缩):没有碎片,效率偏低(两遍扫描,指针需要调整)
4.JVM内存分代模型(用于分代垃圾回收算法)
1.部分垃圾回收器使用的模型
除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型
G1是逻辑分代,物理不分代
除此之外不仅逻辑分代,而且物理分代
2.新生代+老年代+永久代(1.7) / 元数据区Metaspace(1.8)
永久代,元数据区区别:
都是装Class对象的
永久代必须指定大小限制。元数据区可以设置,也可以不设置,无上限(受限于物理内存)
字符串常量在1.7时是存放在永久代的,1.8则在堆里
3.新生代=eden区+2个survivor区
1.YGC回收之后,大多数对象会被回收,活着的利用Copying算法进入survivor区(s0)
2.再次YGC,活着的对象 eden+s0 ->进入s1
3.再次YGC,活着的对象 eden+s1 ->进入s0
4.年龄足够->进入老年代
5.s区装不下->老年代
4.老年代
老年代满了会触发一次FGC(Full GC)
5.GC Tuning(分代算法)
1.尽量减少FGC
MinorGC = YGC
MajorGC = FGC
5.常见的垃圾回收器
JDK诞生 Serial追随 提高效率,诞生了PS。为了配合CMS,诞生了ParNew。CMS是1.4版本后期引入,CMS是里程碑式的GC,它开启了并发回收的过程,但是CMS毛病较多,因此目前没有任何一个JDK版本默认是CMS ,是因为无法忍受STW(stop the world)
ConcurrentMarkSweep 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms) CMS问题比较多,所以现在没有一个版本默认是CMS,只能手工指定 CMS既然是MarkSweep,就一定会有碎片化的问题,碎片到达一定程度,CMS的老年代分配对象分配不下的时候,使用SerialOld 进行老年代回收。
1.Serial:串行回收,单线程(新生代)
2.Parallel Scavenge:并行回收,多线程(新生代)
3.ParNew:配合CMS的并行回收(新生代)
4.Serial Old(老年代)
5.Parallel Old(老年代)
6.CMS(ConcurrentMarkSweep)(老年代)
7.G1(10ms) 算法:三色标记 + SATB (JDK1.9默认G1)
8.ZGC (1ms) 算法:ColoredPointers + LoadBarrier
9.Shenandoah 算法:ColoredPointers + WriteBarrier
10.Eplison
JDK1.8默认的垃圾回收器:Parallel Scavenge + Parallel Old (PS+PO)
垃圾收集器跟内存大小的关系
- Serial 几十兆
- PS 上百兆 - 几个G
- CMS - 20G
- G1 - 上百G
- ZGC - 4T - 16T(JDK13)