上周同事技术分享,本就为菜鸟的我叕忘记了强引用,软引用,弱引用的区别。
本着好记性不如烂笔头的原则,将整理及测试的demo贴出,供之后复习。
-0.0-
一:
1 强引用:
eg: String stongReference = new String(“java”);
对象存活时即使内存溢出也不会进行回收,如果要中断强引用和某个对象之间的关联,可以显示地将引用赋值为null eg:ArraryList的clear方法
2 软引用:
内存足不回收,内存不足回收 ;类:SoftReference
3 弱引用:
内存足或不足都会回收,即gc回收算法扫描到即回收 ;类:WeakReference
Talk is cheap,Show me the code!!!
public class Reference {
public static void main(String[] args) {
1.1 强引用 单直接引用回收测试
String stongReference = new String("java");
System.out.println(stongReference);
stongReference = null;//去掉强引用,gc回收-可达性分析法 判断【new String("java")】这个对象无直接引用,即可进行回收
System.gc();//通知JVM gc进行垃圾回收
System.out.println(stongReference);//null 已回收
System.out.println("---------********------------");
1.2 强引用 多直接引用回收测试
String stongReferenceT = new String("strong");
ArrayList<Object> arrayList = new ArrayList();
arrayList.add(stongReferenceT);
System.out.println(arrayList);
stongReferenceT = null;//去掉强引用,若无其他直接引用,下次gc可回收
System.gc();//通知JVM gc进行垃圾回收
System.out.println(arrayList); //因arrayList中还存在对【new String("java")】对象的直接引用,故无法回收。
System.out.println("---------********------------");
3 软引用
SoftReference<String> sr = new SoftReference<String>(new String("Talk is cheap"));
System.out.println(sr.get());
ArrayList<SoftReference<String>> arrayListSoft = new ArrayList();
arrayListSoft.add(sr);
System.out.println(arrayListSoft);
System.gc(); //通知JVM gc进行垃圾回收,软引用当内存不足时gc才会回收
System.out.println(sr.get());
System.out.println(arrayListSoft.get(0).get());
System.out.println("---------********------------");
3 弱引用
WeakReference<String> wr = new WeakReference<String>(new String("Show me the code"));
System.out.println(wr.get());
ArrayList<WeakReference<String>> arrayListWeak = new ArrayList();
arrayListWeak.add(wr);
System.out.println(arrayListWeak);
System.gc(); //通知JVM gc进行垃圾回收,弱引用直接gc回收
System.out.println(wr.get());
System.out.println(arrayListWeak.get(0).get());
}
}
二:回收策略
引用类型 | GC回收时间 | 用处 | 存活时间 |
---|---|---|---|
强引用 | 从来不会被回收 | 一般对象的引用 | JVM停止运行时 |
软引用 | 在内存不足时 | 对象缓存 | 内存不足时 |
弱引用 | 在垃圾回收时 | 对象缓存 | GC回收后 |
注:关于强引用,可能会有一个疑问
问:String sr = new String(“java”);,stongReference作为强引用存在虚拟机栈中,而new String(“java”)作为对象存在于堆中,当sr的作用域结束,对应的虚拟机栈消失,sr引用也同时消失,但new String(“java”)对象却仍然存在于堆中,“JVM必定不会回收这个对象” ,那jvm不是很容易就OOM了吗?
答:可以手动设置sr=null,这样gc就会主动地将new String(“java”)对象回收,但这样操作太过繁琐;
实际上,“JVM必定不会回收这个对象” 这句话缺少了一个前提,就是这个对象要和强引用还有关联,也就是在根搜索算法中,还和GC Roots相连接,这样jvm就一定不会回收强引用的对象。上述的例子中,sr强引用消失后,new String(“java”)和它的关联也就断了,这样就不再和GC Roots相连接,gc在之后的某个时间就会回收这个对象了。