回顾上期
1)JVM中引用存在哪里?
答:虚拟机栈,该内存空间线程独有
2)该引用的对象存在哪里?
答:堆,所有通过new方法分配的对象都存在堆中
3)String s1="abc",字符串"abc"存在哪里?
答:运行时常量池,且常量池每次存储对象时会查找是否存过相等的对象,如果有,直接引用指向它,不再开辟空间。
如果你三个问题都可以回答出来,恭喜你!上一篇的精髓你get到了~~~~
引用的分类
1) 强引用,默认分配方式均为此类型
Object a=new Object();
2) 软引用,以强引用为参数,构造弱引用
Object a=new Object();
SoftReference<Object> b=new SoftReference<Object>(a);
a=null; //强引用a一定要断掉
System.out.println(b.get()); //通过get()方法返回对象
3) 弱引用
Object a=new Object();
WeakReference<Object> b=new WeakReference<Object>(a);
a=null; //强引用a一定要断掉
System.out.println(b.get()); //通过get()方法返回对象
System.gc();
4)幽灵引用,和没有引用是一样的
引用的特点
1)有强引用指向的对象不会被垃圾回收
2)软引用指向的对象在堆的空间不够时被回收
3)只要系统执行垃圾回收,就会回收软引用
从上面三点中,我们总结出垃圾回收是也是JVM中的一个线程,每执行一次,都要检查对象有没有强引用指向
如果没有再依次考虑软引用和弱引用
那么怎么检查呢?
代码分析
垃圾回收检查算法
1) 计数分析
每个对象,都给一个计数器,每增加一个强引用,就把计数器+1,如果当前计数器的值为0,就回收
思路很简单,但是会发生问题
Object a = new Object(); // a的引用计数为1
Object b = new Object(); // b的引用计数为1
a.next = b; // b的引用计数为2
b.next = a; // a的引用计数为2
a = null; // a的引用计数为1,尽管已经显示地将a赋值为null,但是由于引用计数为1,GC无法回收a
b = null; // b的引用计数为1,同理,GC也不回收b
2) 可达性分析
从GC Root往下搜索,如果该对象是可达的,找到到达该对象的最短路径
最短路径中的强度最弱的引用,决定了该对象是否被回收,如:
GC Root-(弱引用)->1对象-(强引用)->5对象
那么上述两个对象都是要被回收的
另外:GC Root 是什么?一些特殊的对象
虚拟机栈(栈帧中的本地变量表)中引用的对象,往往是方法中的一些简单类型变量
方法区中类静态属性引用的对象
方法区中常量引用的对象