一.判断对象是否已经死去
1.引用计数法
有一次引用,则计数++,当引用失效,则计数--。
缺点,a.ins = b,b.ins = a,则a,b都无法被回收掉。所以没有任何虚拟机采取此方法(i,ie6??)。
2.可达性分析算法
obj4、5、6与gc root没有关联,所以它会被标记为对象已经死亡
GC ROOTS有以下几种:
1.虚拟机栈(栈帧中本地变量表,临时变量)引用的对象类型
2.方法区中静态属性(static)引用的属性
3.方法区中常量引用的对象
4.jni引用的对象
3.引用的三种方式
1.强引用,A a = new A(),只要引用存在,则一直会存在
2.软引用,内存发生溢出前,就会回收掉内存。softreference
3.弱引用,只能存活在下一次gc之前,WeakReference
4.虚引用,唯一目的就是被收集能收到一个通知。
4.finalize的用法
在确定对象与gc root没有关联的时候,需要进行以下判断:
1.是否重写finalize方法
2.是否已执行过finalize方法
如果上面两个条件都满足,那么会执行一次finalize方法,进行“自救”,如果它又被连接到gc roots上,那么自救成功。但是只能自救一次,因为finalize只会执行一次。
回收方法区
条件十分苛刻,需要满足以下三个 1.该类的所有实例已被回收 2.该类的classLoader已被回收 3.该类的Class已经没有被引用。总之,该类不会再被引用到
二.垃圾收集算法
1.标记清除,先标记,后清除,问题是会产生大量的内存碎片。
2.复制算法,内存分为两块,清理的时候,直接将一块中内存还有用的复制到另一块,并且将原内存块清理干净。如果按照1:1来分配,则会造成内存的大量浪费。所以一般采用 一块eden 和两块 suvivor,每次将 eden和suvivor中存活对象复制的新的suvivor中去,将eden和旧suvivor中内存清理掉。但是如果新的suvivor不够的话,则会采取分配担保,直接让suvivor中的部分内容进入older。
3.标记-整理算法 直接让存活对象移动一端,让非存活对象移向另一端,然后抹去非存活对象那一块。
三.hotspot算法实现
1.枚举根节点
枚举根节点需要访问大量的对象,而且这个过程必须要让所有java执行线程暂停(stop the world)。jvm不会去逐个寻找对象,它会用一组OopMap的数据结构来达到这个目的,在类加载完成后,就会生成一份记载对象和其偏移量的OopMap。
2.安全点
OopMap如果频繁更新,会增大负荷。所以有了安全点的概念,只有安全点,才会更新OopMap。同样,只有到安全点,才允许gc,safepoint产生的时机在方法调用,循环跳转,异常跳转等。
如何让gc的时候到达安全点?
a.抢先式,让所有线程中断,如果有线程不在,就让它跑过去。(没人用)
b.主动式,设置一个和安全点重合的轮询标志,线程去轮询这个标志,发现中断标志为真时就自己中断挂起。
3.安全区域
如果有些线程已经暂停,那么他就不能进入safepoint,saferegion是对safepoint的扩展。
四.垃圾收集器
1.serial收集器 (serial old)
serial收集器在收集的时候,会stop the world,单线程收集器。
新生代采取复制算法,老年代采取标记-整理算法。
2.parnew收集器(新生代)
是serial收集器的多线程版本,除了多线程,与serial并无区别。
3.parallel scavenge收集器(新生代收集器)
与parnew的区别在于达到一个可控制的吞吐量(cpu 用于运行用户代码和 cpu总时间的比值 ).
4.parallel old收集器
老年代多线程收集器
5.cms收集器(current mark sweep)
老年代收集器,需要配合parnew收集器使用,以最短回收停顿时间为目标,基于 标记-清除 算法,分为以下四个阶段。
a.初始标记 stop the world
b.并发标记 并行
c.重新标记 stop the world
d.并发清除 并行
缺点,在多线程上才有优势,无法处理浮动垃圾,会产生碎片。
6.g1收集器
优点:a.可以并发执行 b.保留分代的概念 c.空间整合 d.可预测的停顿 在m毫秒内,消耗不超过n秒
a.初始标记 stop the world
b.并发标记 并行
c.最终标记 stop the world
d. 并行
五.内存分配与回收策略
1.对象优先分配在eden,minor gc会清理eden和survivor区域里面的对象,older需要 major/full gc来回收,往往伴随一次minor gc,时间是minor gc的十倍。
2.大对象直接进入老生代
3.长期存活对象进入老年代
4.如果suvivor中相同年龄对象超过内存一半,则大于等于该年龄的对象会直接进入老年代。
5.虚拟机会检查 older最大连续可用空间是否大于 eden,如果是,则minor gc安全。如果不是,会检测older连续空间是否大于 每次晋升的平均大小,并且尝试 minor gc,这是不一定成功的,失败会进行full gc。