一、引用计数
Java在GC时会看这个对象是否与其他引用有关联,如果存在引用关系则表示这个对象还有用,不能被回收,如果不存在引用关系则可基本定性为可被回收的对象。优点:效率高;缺点:无法解决循环引用的问题。如下代码:
public class Main {
public static void main(String[] args) {
MyObject object1 = new MyObject();
MyObject object2 = new MyObject();
object1.object = object2;
object2.object = object1;
object1 = null;
object2 = null;
}}
class MyObject{
public Object object = null;}
当object1和object2赋值为null,也就是说object1和object2指向的对象已经不可能再被访问了,但是由于他们互相引用对方,导致引用计数不为0,垃圾回收期永远不会回收它们。因此java没有采用这种方式。
二、可达性分析
为了解决循环引用的问题,Java采用了可达性分析的方式,主要是通过Roots对象作为起点进行搜索,搜索的路径被称为“引用链”,当一个对象到Roots没有任何引用链相连的时,证明此对象不可用,当然被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就会成为可回收对象。能够被回收其实主要看finalize()方法有没有与引用链上的对象关联,如果在finalize()方法中有关联则自救成功,该对象不可被回收,反之如果没有关联则成功被 二次标记,就可以称为要被回收的垃圾了。
三、Roots对象
- 虚拟机栈中引用的对象
- 方法区中类静态属性引用的对象
- 本地方法栈引用的对象
四、引用类型
- 强引用(Strong):类似 A a = new A();不会被回收
- 软引用(Soft):在jvm要内存溢出时,会回收软引用的对象,释放内存
- 弱引用(Weak):在下次GC时,弱引用的对象会被回收
- 虚引用(Phantom):无法引用对象实例,唯一的作用就是在该对象被回收时会收到一个系统通知,如WeakHashMap,业务场景缓存