垃圾回收(Garbage Collection),采用分代收集算法思想,频繁收集年轻代,较少收集老年代,基本不动永久代。
按照回收区域又分为两种类型,一种只针对年轻代的Minor Gc,另一种针对老年代偶尔伴随着新生代的Major Gc。
垃圾指内存中不再使用的空间,如没有任何栈引用对象指向的堆内存空间。
垃圾分类:
⑴ 强引用(StrongReference)【不是垃圾】:常见的普通对象引用,就算出现了OOM也不会对该对象进行回收
。
⑵ 软引用(SoftReference)【可能是垃圾】:需要SoftReference类实现,内存空间不足了,垃圾回收器就会回收它
。
⑶ 弱引用(WeakReference)【垃圾】:需要WeakReference类实现,只要GC,对象就被回收
。
⑷ 虚引用(PhantomReference):虚引用主要用来跟踪对象被垃圾回收器回收的活动
。
⑴ 引用计数法:存在“循环依赖”问题,弃用
;
⑵ 枚举根节点做可达性分析法:通过一些被称为垃圾回收根(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时(即从 GC Roots 节点到该节点不可达),则证明该对象是不可用的
;
GC Root:是一组必须活跃的引用
。
可作为 GC Root 的对象包括以下4种:
① 栈(栈帧中的本地变量表)中引用的对象
;
② 方法区中类静态属性引用的对象
;
③ 方法区中常量引用的对象
;
④ 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
;
Minor GC: Eden区满了或者新创建的对象大小大于Eden所剩空间;
Major GC: 老年代空间不足、永久代空间不足、minor gc时出现promotion failure、显示调用System.gc();
注释:
promotion failure,是在minor gc过程中,survivor的剩余空间不足以容纳eden及当前在用survivor区间存活对象,只能将容纳不下的对象移到年老代(promotion),而此时年老代满了无法容纳更多对象,通常伴随full gc,因而导致的promotion failure。这种情况通常需要增加年轻代大小,尽量让新生对象在年轻代的时候尽量清理掉。
复制算法(Minor GC使用的算法):
从GC Root开始,通过Tracing 从Eden 和 From区找到存活对象,拷贝到To区。GC完成后,From、To交换身份,下次内存分配从To区开始。存活的对象每经历一次Minor GC ,年龄会加1,当达到某个阀值(默认15,可通过-XX:MaxTenuringThreadshold配置)就会成为老年代对象。
标记-清除(Major GC使用的算法):
当堆中有效空间被耗尽,会暂停整个程序(stop the world)进行标记和清除。
标记:从GC Root开始扫描,标记存活的对象(GC Root可达对象);
清除:遍历整个堆,清除未被标记的对象;
标记-压缩(Major GC使用的算法):
标记:从GC Root开始扫描,标记存活的对象(GC Root可达对象);
压缩:遍历整个堆,将标记的对象往一端移动,直接清除边界以外的内存;
标记-清除-压缩(Major GC使用的算法):
- Mark-Swap 和 Mark-Compact的结合;
- 和Mark-Swap 一致,当进行多次GC后才Compect;
小总结:
年轻代Minor GC使用复制算法;
老年代Major GC使用标记-清除 和 标记-清除-压缩算法;
内存效率: 复制算法 > 标记清除 > 标记压缩;
内存整齐度:复制算法 = 标记压缩 > 标记清除;
内存利用率:标记清除 = 标记压缩 > 复制算法;