一、概述
Garbage Collection,释放被垃圾占用的空间
二、垃圾判断算法
1、引用计数法
给对象添加一个计数器,新增引用时加1,减少引用时减1,当计数为0时判定为垃圾,可以被释放。缺点:无法解决循环引用的问题。
2、可达性分析法
通过GC ROOT对象作为搜索起点,通过引用向下搜索,所走过的路径叫做引用链。通过对对象判断是否有到达引用链的路径来判定是否可被回收。
GC ROOT对象:
虚拟机栈中引用的对象
静态属性引用的对象
常量引用的对象
本地方法栈中JNI引用的对象
三、垃圾回收算法
1、标记清除算法
将可释放的内存空间标记起来,然后清理掉。缺点:由于被清理掉的内存不连续,会产生很多的内存碎片。
2、复制清除算法
将内存分为相等的两部分,每次只使用一部分,当这部分内存满了时,标记可释放的内存空间,把活着的对象复制到没有使用到的部分,然后清除原来使用的内存。缺点:每次只能有半的内存空间可使用。
3、标记整理法
标记对象,将所有存活的对象,向一端移动,清理掉边界外的内存。
标记整理算法解决了内存碎片的问题,也规避了复制算法只能利用一半内存区域的弊端。标记整理算法对内存变动更频繁,需要整理所有存活对象的引用地址,在效率上比复制算法要差很多。
四、内存区域与回收策略
当一个对象创建时,优先分配到Eden区,如果Eden区空间不够是触发Minor GC。将内部存活对象复制到survivor区,Survivor区分为两部分S1、S2(空间大小,Eden:S1:S2=8:1:1),首先将存活对象复制到S1,清理Eden区,当Eden再满时触发Minor GC,将S1中的对象和Eden中存活的对象放入S2,并计次。以此类推,达到一定复制次数的对象会进入到Old区。此时如果对象大于S1,直接进入Old区。Old区空间不足时会触发Major GC,Major GC所耗费的时间要超过minor GC很多。
MinorGC触发时机:
Eden区满时,在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象的总空间。只要老年代的连续空间大于新生代对象的总大小或者历次晋升到老年代的对象的平均大小就进行MinorGC,否则FullGC。
Major GC/FullGC触发时机:
1.System.gc()方法的调用
2.老年代空间不足
3.CMS GC时出现promotion failed和concurrent mode failure
4.通过Minor GC后进入老年代的平均大小大于老年代的可用内存