一.对象是否存活判断
1.引用计数法
给对象添加引用计数器,一个地方引用它计时器值+1;当引用失效,计数器值-1;计数器为0的对象表示对象不可能引用。
缺陷:难以解决对象之间循环引用的情况
objA = objB;
objB = objA;
除此之外,这两个对象再无任何引用,但由于按照引用计数法他们的计数值都不为0,故不能被GC收集。
2.可达性分析算法
这个算法的基本思路是:通过一些系列"GC Roots
“的对象作为起始点,从这些节点向下搜索,搜索走过的的路径称为”引用链
"。当一个对象与GCRoots之间不存在一条引用链时,即它不可达GC_Roots,则它会被判定为可回收的对象。
根据图论理解:那些可以被回收的对象不存在一条路径到达GC_Roots。
GC_Roots对象可以是:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象
2.方法区中类静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中JNI(即一般说的Native方法)引用的对象
关于引用
在JDK1.2之后,java对引用的概念进行扩充,将引用分为:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Week Reference)、虚引用(Phantom Reference)。并提供相应的类用来实现我们的引用。
强引用:
指在程序代码中普遍存在的,类似“Object obj = new Object()”这样的引用,只要强引用还在,GC就不会回收该对象。
软引用:
用来描述一些有用但非必须的对象,对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象后列进回收范围之中进行第二次回收。如果这次回收还没有足够内存,才会抛出OOM。
弱引用:
用来描述非必须对象,但是它比软引用更弱一些,被弱引用关联的对象只能活到下一次GC发生之前。当GC时,无论内存是否足够,都会回收该对象。
虚引用:
也称为幽灵引用或幻影引用,它是最弱的一种引用关系。虚引用的存在,不会对对象的存活时间构成影响,但也不能通过虚引用实例化该对象。为该对象设置虚引用的唯一目的是:在该对象被GC回收时收到一个系统通知。
生存还是死亡
在可达性分析算法中那些不可达的对象,也并非是"非死不可",这时候它们处于"缓刑"阶段。真正宣告一个对象死亡,至少要经历两次标记过程:
在可达性分析过程中不可达的对象,会被标记一次,并且进行筛选,筛选条件:是此对象是否有必要执行finalize()方法。
当对象没有覆盖finalize()方法,或者finalize()方法被虚拟机调用过,则虚拟机会视为"没有必要执行"。
对于有必要执行finalize()方法的对象,将会把这个对象放入F-Queue队列中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去触法它的finalize()方法,(但虚拟机并不承诺会等待这个方法执行结束,这样做的原因是由于一个对象的finalize()方法里面可能进行了耗时操作,从而导致F-Quene队列等待时间过长,甚至导致GC崩溃)在这个方法中对象可以进行自救,只要在该方法内把对象引用与GC_Roots上任意一个结点关联起来就会使它自救成功。它会在第二次标记时从"即将回收"的集合移除,如果此时自救失败,那对象基本上会被回收掉。
一个对象 finalize()方法只能调用一次,即第一次可以帮助对象逃离,但第二次就会失效。并且此方法的缺点是:使用需要高昂的运行代价,不确定性大,无法保证各个对象的调用顺序。
finalize()能做的工作,可以被try-finally或其他方式做的更好、更及时。
二.垃圾收集算法
1.标记-清除算法
分为
标记阶段:标记出所有需要回收的对象
清除阶段:在标记完成后,统一进行回收所有被标记的对象。
不足:效率慢,标记和清除两个过程的效率都不高;空间碎片化,标记-清除后会产生大量不连续的内存碎片,会导致以后程序运行过程中需要给分配一个比较大的对象时,找不到一块足够大的连续内存分配给它,从而不得不提前触发一次垃圾收集操作。
2.复制算法
复制算法的出现是为了解决上面存在的效率问题。
思想:将内存分为等大的两块,每次只用一块,当这一块用完时,就将还存活的对象复制到另一块上面,然后把满了的这块内存清理掉。
优点:实现简单,运行高效
不足:牺牲了一般的内存
发展:考虑到新生代的对象98%都死是"朝生夕死"的特性,将内存分为一个较大的Eden空间和两个较小的Survivor空间,每次使用Eden空间和其中一个Survivor,回收时将上述两部分内存上还存活的对象,复制到没使用的Survivor上,然后清理之前使用的那两块内存。
HotSpot虚拟机默认Eden和Survivor空间比例8:1。
即每次可以使用80%+10%的内存,用10%的内存来存储最终存活的对象。但是,我们没有办法保证每次回收存活对象占用内存不多于10%,当