Java引用概述
引用是开发的灵魂,直接决定了对象占用内存的时间,在JDK1.2之后提出了四种引用方式
1、 强引用:当JVM空间不足,JVM宁可出现OutOfMemoryError错误停止,也需要空间保存,并且不回收空间 Object obj=new Object()
2、 软引用:当内存不足,进行对象回收处理,往往用于高速缓存Mybaits
3、 弱引用:不管内存是否紧张,有垃圾就回收;
4、 幽灵引用:和没有引用是一样的(简单讨论,介绍引用队列)
2.1:强引用:
JVM默认的支持模式,即:在引用期间内,如果该堆内存被指定的栈内存有联系,那么该对象就无法被GC所回收,一旦出现内存空间不足,就会出现“OutOfMemeryError”的错误信息。
例子:
Object object = new Object();//强引用,默认支持
Object ref = object;//引用传递
object = null;//断开一个连接
System.gc();
System.out.println(ref);//结果 java.lang.Object@7852e922
堆内存有任何一个栈内存指向,那么该内存无法被回收
这是我们开发中主要的使用模式,正是因为强引用具备这样的内存分配异常问题,所有我们的开发原则是尽量少实例化对象。
2.2 软引用
在许多开源组件中往往使用软引用作为缓存组件出现,最大特点是:内存不足就回收,充足不回收
构造函数:public SoftReference(T referent)
取出数据:public T get()
例子(为了看出效果,做了内存的配置):
// -Xmx10M -Xms10M -XX:+PrintGCDetails
Object object = new Object();//强引用,默认支持
SoftReference<Object> reference = new SoftReference<Object>(object);
object = null;
final String STR = "111111111111111111111111111111111111111111111111111111111111111111111111111";
String string = "";
try {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
string = string + STR;
string.intern();
}
} catch (Throwable e) {
// TODO: handle exception
}
System.out.println(reference.get());//结果:null
2.3弱引用
一旦发生GC就回收,弱引用需要使用Map接口的子类java.util. WeakHashMap
例一:
String key = new String("swust");
String value = new String("www.swust.edu.cn");
WeakHashMap<String, String> map = new WeakHashMap<String, String>();
map.put(key, value);
key = null; //断开强引用
value = null;//断开强引用
System.out.println(map);//输出结果:{swust=www.swust.edu.cn}
System.gc();
System.out.println(map);//输出结果:{}
例二:
Object object = new Object();//强引用,默认支持
WeakReference<Object> reference = new WeakReference<Object>(object);
object = null;
System.out.println(reference.get());//结果:java.lang.Object@7852e922
System.gc();
System.out.println(reference.get());//结果:null
一旦GC就回收,对开发不利,要慎用。
引用队列
引用队列:保存那些准备被回收的对象,很多时候的对象回收扫描都是从根对象开始的
那么对于整个的GC而言,如果要想确定那些对象可以被回收,就必须确定好引用的强度,这个就是所谓的引用路径的设置
找到对象5 有两条路径{(根集,对象1,对象5),强+软},{(根集,对象2 对象5),强+弱},软引用比弱引用保存强,实际上这个时候对于对象的引用而言,如果要进行引用的关联判断,那么就必须找到强关联,为了避免非强关联带来的内存引用问题,提供了一个引用队列的概念。如果在创建软引用或者引用弱引用使用了引用队列的方式,则这个对象被回收之后会自动保存在引用队列之中。
例子
Object object = new Object();//强引用,默认支持
ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
@SuppressWarnings("unused")
WeakReference<Object> reference = new WeakReference<Object>(object, queue);
object = null;
System.out.println(queue.poll());//null
System.gc();
try {
Thread.sleep(100);//稍微停顿一下
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(queue.poll());//结果:java.lang.ref.WeakReference@7852e922
幽灵引用(虚引用,基本不用)
永远取得不了的数据就叫幽灵引用,必须和引用队列(ReferenceQueue)联合使用。