在回收垃圾前,需要判断哪些是垃圾,哪些不是。
原理:被引用+1,未被引用-1,为0时回收。
问题:无法解决循环引用的问题
通过GC Roots作为起点遍历,判断是否被引用。
GC Roots包括:
【引用的判定】
分代收集本质上就是分类讨论,根据对存活对象的预判,采用效率更高的收集算法。
先通过GC Roots遍历,标记不可达对象,而后清除。
问题:产生不连续的空间碎片
折半内存,将存活对象复制到另一半内存中,然后把当前内存全部回收。
问题:解决了空间碎片,但只能使用一半的内存
将存活对象移动到内存的一端,然后清除边界之外的所有内存。
【既不会产生空间碎片,也不会导致内存折半】
分代算法,就是根据 JVM 内存的不同内存区域,采用不同的垃圾回收算法。
例如对于存活对象少的新生代区域,比较适合采用复制算法。这样只需要复制少量对象,便可完成垃圾回收,并且还不会有内存碎片。
而对于老年代这种存活对象多的区域,比较适合采用标记清除算法或标记整理算法,这样不需要移动太多的内存对象。
Serial回收器是一种单线程串行回收器,使用复制算法,在执行回收时会产生较长时间的停顿,优点是不会产生线程切换的开销
通过JVM参数-XX:+UseSerialGC可以使用串行垃圾回收器。
SO回收器是一种多线程并行回收器,使用标记整理算法,适用老年代
PN回收器是一种多线程并行器,使用复制算法。
参数控制:-XX:+UseParNewGC
PO是一种多线程回收器,使用标记整理算法,适用老年代
PS回收器也是一种多线程并行回收器,使用复制算法,特点是可设置吞吐量
参数:-XX:+UseParallelGC
CMS使用标记清除算法,主要目的是回收时的低停顿。
过程:
问题:
特点:
分区思路:
为什么使用分区:针对老年代的操作需要扫描所有的老年代空间;由于连续,必须分配年轻代和老年代的地址位置
G1之前的内存都是连续的:
G1回收器的内存按区等分,分为eden,survivor,old和humongous:
G1回收器回收流程:
Minor GC 和Full GC
从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC。当 JVM 无法为一个新的对象分配空间时会触发 Minor GC,比如当 Eden 区满了。
Full GC 是清理整个堆空间—包括年轻代和永久代。
Full GC执行条件: