java弱引用代码 java 弱引用( 四 )


public class TestOOM {
private static ListObject list = new ArrayList();
public static void main(String[] args) {
testSoftReference();
}
private static void testSoftReference() {
for (int i = 0; i10; i++) {
byte[] buff = new byte[1024 * 1024];
SoftReferencebyte[] sr = new SoftReference(buff);
list.add(sr);
}
System.gc(); //主动通知垃圾回收
for(int i=0; ilist.size(); i++){
Object obj = ((SoftReference) list.get(i)).get();
System.out.println(obj);
}
}
}
打印结果:
我们发现无论循环创建多少个软引用对象 , 打印结果总是只有最后一个对象被保留,其他的obj全都被置空回收了 。
这里就说明了在内存不足的情况下 , 软引用将会被自动回收 。
值得注意的一点 , 即使有 byte[] buff 引用指向对象, 且 buff 是一个strong reference, 但是 SoftReference sr 指向的对象仍然被回收了,这是因为Java的编译器发现了在之后的代码中, buff 已经没有被使用了, 所以自动进行了优化 。
如果我们将上面示例稍微修改一下:
private static void testSoftReference() {
byte[] buff = null;
for (int i = 0; i10; i++) {
buff = new byte[1024 * 1024];
SoftReferencebyte[] sr = new SoftReference(buff);
list.add(sr);
}
System.gc(); //主动通知垃圾回收
for(int i=0; ilist.size(); i++){
Object obj = ((SoftReference) list.get(i)).get();
System.out.println(obj);
}
System.out.println("buff: " + buff.toString());
}
则 buff 会因为强引用的存在,而无法被垃圾回收,从而抛出OOM的错误 。
如果一个对象惟一剩下的引用是软引用,那么该对象是软可及的(softly reachable) 。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正 “需要” 内存时才收集软可及的对象 。
三 , 弱引用
弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收 。在 JDK1.2 之后 , 用 java.lang.ref.WeakReference 来表示弱引用 。
我们以与软引用同样的方式来测试一下弱引用:
private static void testWeakReference() {
for (int i = 0; i10; i++) {
byte[] buff = new byte[1024 * 1024];
WeakReferencebyte[] sr = new WeakReference(buff);
list.add(sr);
}
System.gc(); //主动通知垃圾回收
for(int i=0; ilist.size(); i++){
Object obj = ((WeakReference) list.get(i)).get();
System.out.println(obj);
}
}
打印结果:
可以发现所有被弱引用关联的对象都被垃圾回收了 。
四,虚引用
虚引用是最弱的一种引用关系 , 如果一个对象仅持有虚引用,那么它就和没有任何引用一样 , 它随时可能会被回收 , 在 JDK1.2 之后 , 用 PhantomReference 类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象 , 虚引用必须要和 ReferenceQueue 引用队列一起使用 。
public class PhantomReferenceT extends ReferenceT {
/**
* Returns this reference object's referent.Because the referent of a
* phantom reference is always inaccessible, this method always returns
* codenull/code.
*
* @returncodenull/code
*/
public T get() {
return null;
}
public PhantomReference(T referent, ReferenceQueue? super T q) {
super(referent, q);
}
}
那么传入它的构造方法中的 ReferenceQueue 又是如何使用的呢?

推荐阅读