- 前言
- 判断一个对象是否是垃圾
- 引用计数法
- 可达性分析
- 回收垃圾的算法
- 标记清除算法
- 复制算法
- 标记整理算法
- 分代垃圾回收算法
GC:Garbage Collection(垃圾回收)找到内存空间的垃圾,回收垃圾。
Java的四种引用状态:
在IDK1.2之前,Java中的引用:如果引用类型的数据中存储的数值代表的是另一块内存的其实地址,就成这块内存代表一个引用。那么一个对象只有“已被引用”和“未被引用”两种状态,这将无法描述某些特殊情况下的对象,比如,当内存充足时需要保留,在内存紧张时才需要被回收的一类对象。在JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用,软引用,弱引用,虚引用。
强引用:是最常用的引用类型,只要强引用存在,垃圾回收器永远不会回收被引用的对象,哪怕内存不足,JVM会直接抛出OutOfMemory Error也不会回收。如果要回收被强引用的对象:主动切断对象的强引用,即将引用赋值为null。
Object o=new Object(); //这类的引用都是强引用 o=null; //切断强引用
软引用:描述一些仍有用但非必须的对象。在内存足够时,软引用对象不会被回收,只有在内存不足时,系统会回收软引用对象。如果这次回收还没有足够的内存空间,才会抛异常。JDK1.2之后的Java的SoftReference类来实现软引用。
Object o=new Object(); SoftReference sr=new SoftReference(o);
弱引用:弱引用也是用来描述非必须对象的。当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在Java用WeakReference表示弱引用。
虚引用:虚引用并不影响对象的生命周期。在Java中PhantomReference表示。如果一个对象仅持有虚引用,它就和没有任何引用一样,随时会被回收。
为一个对象设置虚引用的唯一目的是希望能在这个对象被垃圾回收时收到一个系统通知。
引用队列:引用队列可以与软引用、弱引用和虚引用一起配合使用,当垃圾回收器准备回收一个对象时,如果发现它还有引用,那么就会在回收对象之前,把这个引用加入到与之相关联的引用队列中去。这样可以用来判断被引用的对象是否将要被垃圾回收,可以在对象被回收之前采用一些必要的措施。虚引用必须和引用队列一起使用。
判断一个对象是否是垃圾有两种算法:1.引用计数法 2.可达性分析算法
引用计数法给对象中添加一个引用计数器,每当一个地方引用这个对象,计数器值+1,,当引用失效时,计数器值-1。任何计数为0的对象可以被当做垃圾回收。
但是这种算法无法解决两个对象相互引用的情况:
早期的JVM使用了引用计数法,现在绝大多数JVM采用可达性分析算法。
基本思路是,通过一些被称为垃圾回收根(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路称为引用链(Reference Chain),当一个对象到GC Roots没有任何的引用连相连时,则证明该对象是不可用的。
object5和object6没有到达GC Root的引用链,即使它们之间相互引用也还是会被回收。
可作为GC Roots的对象包括以下几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(Native方法)引用的对象
是最基础的一种垃圾回收算法。分为标记,清除和分配3个阶段。
标记阶段就是遍历对象并标记的处理过程。
清除阶段
- 遍历堆,具体来说就是从堆首地址开始,按顺序一个个遍历对象的标志位。
- 回收对象就是把对象作为分块,连接到被称为“空闲链表”的单向链表。在之后进行分配时只要遍历这个空闲链表,就可以找到分块了。
- 在清除阶段,程序会遍历所有堆,进行垃圾回收。也就是说,所花费时间与堆大小成正比。堆越大,清除阶段所花费的时间就会越长。
分配阶段:将分配的内存进行回收再利用。
缺点:标记清除后会产生大量的不连续的内存碎片。需要一个空闲列表记录所有的空闲区域及大小。
复制算法是在标记清除算法上演化过来的,解决内存碎片化问题。
它将可用的内存分为两块,每次只用其中的一块,当这一块内存用完了,就将还存活的对象复制到另一块上面,把使用过的内存一次清理掉。
回收前:
回收后:
缺点:内存的有效使用率太低。
标记整理算法和标记清除算法一样,只是后续步骤不是直接回收对象进行清理,而是让所有存活的对象向一端移动,然后直接清理端边界以外的内存。
回收前:
回收后:
分代垃圾回收中把对象分类成几代,针对不同的代使用不同的 GC 算法,我们把刚生成的对象称为新生代对象,到达一定年龄的对象则称为老年代对象。
在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,选用复制算法。在老年代中因为对象存活率高,没有额外空间对它进行分配担保,必须使用标记清除算法或者标记整理算法来进行回收。



