java的弱,虚,软引用介绍
1.弱,虚,软引用的介绍
对于绝大部分的对象而言,在程序中是存在着一个引用变量引用该对象,这是常见的引用方式,也就是常说的 强引用,对于强引用引用的对象,系统JVM是不会随意的回收资源,但是区别于强引用,对于内存敏感的程序,我们
这个内存敏感我也不清楚是啥,书上是这样说的,个人理解可能就是对于内存开支需求比较大的
也常常可以使用java.lang.ref下提供的三个包:
- SoftReference
- PhantomReference
- WeakReference
这三个类分别代表了三种引用,分别是软引用,虚引用和弱引用。
2.对于四种引用的区别
- 强引用:代表对象处于可达状态,不能被系统垃圾回收机制所回收
- 软引用:当一个对象只有软引用的时候,可能被垃圾回收机制所回收,当内存空间足够,就不会回收,内存空间不够就另当别论
- 弱引用:只要进行垃圾回收,就会对于这个对象进行回收,变为可恢复状态
- 对于对象本身没有太大的影响,甚至对象是感受不到虚引用的存在的,虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,必须结合队列(ReferenceQueue)联合使用
对象在内存中的三种状态,分别是可达状态,可恢复状态,死亡状态
除了强引用外,其他三种引用类都有一个get()方法获取引用的对象
3.对于引用队列(ReferenceQueue)的介绍
对于软引用和弱引用,在回收完毕之后,把引用的对象和相关的引用添加到关联的引用队列之中
对于虚引用,在回收之前,把对象对应的虚引用添加到相关的队列之中,这使得可以在对象被回收之前采取行动
软引用和弱引用可以单独使用,但是虚引用一般是用来追踪对象与垃圾回收的状态,程序可以通过检查与虚引用相关的引用队列中是否包含了这个虚引用来了解这个对象是不是快要回收了
弱引用的例子
public static void main(String[]__) throws Exception
{
//创建一个字符串对象,注意要使用new方法,而不是直接string a=“xxx”,这样字符串会在常量池导致无法回收
String str=new String("山威");
//创建一个弱引用,让弱引用引用这个str
ReferenceQueue<String> que=new ReferenceQueue<>();
WeakReference<String> wr=new WeakReference<String>(str,que);
//切断str与字符串的联系
str=null;
//在这里取出弱引用对象
System.out.println(wr.get());
//在这里进行内存回收
System.gc();
System.runFinalization();
System.out.println(wr.get());
//再次从队列取出来看看
System.out.println(que.poll().get());
}
这里是代码输出的结果,可以看到在强制垃圾回收之后,弱引用丢失了对象,而队列那个嘛,是我加进去试试的,其实引用队列我也不太会,hhh
内存中的样子
虚引用的列子
public static void main(String[]__) throws Exception
{
//创建一个字符串对象,注意要使用new方法,而不是直接string a=“xxx”,这样字符串会在常量池导致无法回收
String str=new String("山威");
//创建一个弱引用,让弱引用引用这个str
ReferenceQueue<String> que=new ReferenceQueue<>();
PhantomReference<String> ph=new PhantomReference<String>(str,que);
//切断str与字符串的联系
str=null;
//在这里取出弱引用对象
//不会输出东西,因为不能使用虚引用访问对象
System.out.println(ph.get());
//在这里进行内存回收
System.gc();
System.runFinalization();
//回收之后,虚引用进入队列
//再次从队列取出来看看
System.out.println(que.poll()==ph);
}
输出结果
进入队列之后判断,所以这里最后一个输出是true
4.作用分析
使用这些引用类可以避免在程序执行期间将对象留在内存中。如果以软引用、弱引用或虚引用的方式引用对象,垃圾收集器就能够随意地释放对象。如果希望尽可能减小程序在其生命周期中所占用的内存大小时,这些引用类就很有用处。
必须指出:要使用这些特殊的引用类,就不能保留对对象的强引用;如果保留了对对象的强引用,就会浪费这些引用类所提供的任何好处。 《java疯狂讲义》
//取出弱引用所引用的对象
obj=wr.get();
//如果取出的对象为null
if (obj==null)
{
//重新创建一个新的对象,并使用强引用来引用它
obj=recreateIt();
//取出弱引用所引用的对象,将其赋给obj变量
wr=new WeakReference(obj);
}
...//操作obj对象
//再次切断obj和对象之间的关联
obj=null;
例子也是使用 《java疯狂讲义》的,这书除了讲的太细了,其他都好