java reference


import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;

public class ReferenceTest {
/*
*
SoftReference
SoftReference 在“弱引用”中属于最强的引用。SoftReference 所指向的对象,当没有强引用指向它时,会在内存中停留一段的时间,
垃圾回收器会根据 JVM内存的使用情况(内存的紧缺程度)以及 SoftReference 的 get() 方法的调用情况来决定是否对其进行回收。
具体使用一般是通过 SoftReference 的构造方法,将需要用弱引用来指向的对象包装起来。当需要使用的时候,
调用 SoftReference 的 get() 方法来获取。当对象未被回收时 SoftReference 的 get() 方法会返回该对象的强引用

软引用有以下特征:
1. 软引用使用 get() 方法取得对象的强引用从而访问目标对象。
2. 软引用所指向的对象按照 JVM 的使用情况(Heap 内存是否临近阈值)来决定是否回收。
3. 软引用可以避免 Heap 内存不足所导致的异常。

当垃圾回收器决定对其回收时,会先清空它的 SoftReference,也就是说 SoftReference 的 get() 方法将会返回 null,
然后再调用对象的 finalize() 方法,并在下一轮 GC 中对其真正进行回收。

WeakReference
WeakReference 是弱于 SoftReference 的引用类型。弱引用的特性和基本与软引用相似,区别就在于弱引用所指向的对象只要进行系统垃圾回收,
不管内存使用情况如何,永远对其进行回收(get() 方法返回 null)

弱引用有以下特征:
1.弱引用使用 get() 方法取得对象的强引用从而访问目标对象。
2.一旦系统内存回收,无论内存是否紧张,弱引用指向的对象都会被回收。
3.弱引用也可以避免 Heap 内存不足所导致的异常。

PhantomReference
PhantomReference 是所有“弱引用”中最弱的引用类型。不同于软引用和弱引用,虚引用无法通过 get() 方法来取得目标对象的强引用从而使用目标对象,
观察源码可以发现 get() 被重写为永远返回 null。那虚引用到底有什么作用?其实虚引用主要被用来 跟踪对象被垃圾回收的状态,
通过查看引用队列中是否包含对象所对应的虚引用来判断它是否 即将被垃圾回收,从而采取行动。它并不被期待用来取得目标对象的引用,而目标对象被回收前,
它的引用会被放入一个 ReferenceQueue 对象中,从而达到跟踪对象垃圾回收的作用。所以具体用法和之前两个有所不同,它必须传入一个 ReferenceQueue
对象。当虚引用所引用对象被垃圾回收后,虚引用会被添加到这个队列中。

值得注意的是,对于引用回收方面,虚引用类似强引用不会自动根据内存情况自动对目标对象回收,Client 需要自己对其进行处理以防 Heap 内存不足异常

虚引用有以下特征:
1.虚引用永远无法使用 get() 方法取得对象的强引用从而访问目标对象。
2.虚引用所指向的对象在被系统内存回收前,虚引用自身会被放入 ReferenceQueue 对象中从而跟踪对象垃圾回收。
3.虚引用不会根据内存情况自动回收目标对象


小结:
另外值得注意的是,其实 SoftReference, WeakReference 以及 PhantomReference 的构造函数都可以接收一个 ReferenceQueue 对象。
当 SoftReference 以及 WeakReference 被清空的同时,也就是 Java 垃圾回收器准备对它们所指向的对象进行回收时,调用对象的 finalize() 方法之前,
它们自身会被加入到这个 ReferenceQueue 对象中,此时可以通过 ReferenceQueue 的 poll() 方法取到它们。而 PhantomReference
只有当 Java 垃圾回收器对其所指向的对象真正进行回收时,会将其加入到这个 ReferenceQueue 对象中,这样就可以追综对象的销毁情

*/
public static void main(String[] args) throws Exception {
// 设置jvm参数
// -Xmx2m -Xms2m

// test_weakReference();
// test_weakReference2();
// test_softReference();
// test_phantomReference();

// 测试oom时,把finalize方法的打印语句注释掉
// test_strongReference_OOM();
// test_weakReference_OOM();
// test_softReference_OOM();
test_phantomReference_OOM();
}

// result:
// weak ref
// weak ref is finalizing at Sat Feb 08 23:54:17 CST 2014
// null (可能不为null,因为gc不一定执行)
static void test_weakReference() throws Exception {
// 声明一个弱引用
Reference<Bean> ref = new WeakReference<Bean>(new Bean("weak ref"));
// WeakReference通过get方法返回指向目标对象的强引用
System.out.println(ref.get());

// 建议jvm进行gc
System.gc();
System.runFinalization();
TimeUnit.SECONDS.sleep(3);

// 一旦jvm执行gc,会调用Reference的clear方法,清空referent,此时get方法返回值为null
System.out.println(ref.get());
}

// result:
// false
// weak ref
// null
// weak ref is finalizing at Sun Feb 09 00:08:00 CST 2014
// true
// null
// java.lang.ref.WeakReference@16caf43
static void test_weakReference2() throws Exception {
ReferenceQueue<Bean> queue = new ReferenceQueue<Bean>();
Reference<Bean> ref = new WeakReference<Bean>(new Bean("weak ref"),
queue);
// 如果该引用对象被加入到关联的queue中了,返回true
System.out.println(ref.isEnqueued());
System.out.println(ref.get());
System.out.println(queue.poll());

System.gc();
System.runFinalization();
TimeUnit.SECONDS.sleep(3);

System.out.println(ref.isEnqueued());
System.out.println(ref.get());
System.out.println(queue.poll());
}

// result:
// soft ref
// soft ref is finalizing at Sun Feb 09 00:13:29 CST 2014
// null
static void test_softReference() throws Exception {
Reference<Bean> ref = new SoftReference<Bean>(new Bean("soft ref"));
System.out.println(ref.get());

// 模拟消耗内存操作
SoftReference<String>[] garbage = new SoftReference[100000];
for (int i = 0; i < garbage.length; i++) {
garbage[i] = new SoftReference<String>(new String("gb"));
}

TimeUnit.SECONDS.sleep(3);

System.out.println(ref.get());
}

// result:
// null
// false
// null
// phantom ref is finalizing at Sun Feb 09 00:16:26 CST 2014
// null
// true
// java.lang.ref.PhantomReference@60aeb0
static void test_phantomReference() throws Exception {
ReferenceQueue<Bean> queue = new ReferenceQueue<Bean>();
Reference<Bean> ref = new PhantomReference<Bean>(
new Bean("phantom ref"), queue);
// PhantomReference的get方法永远返回null
System.out.println(ref.get());
System.out.println(ref.isEnqueued());
System.out.println(queue.poll());

System.gc();
TimeUnit.SECONDS.sleep(3);
System.gc();

System.out.println(ref.get());
System.out.println(ref.isEnqueued());
System.out.println(queue.poll());
}

static final int SIZE = 100000;

// OOM
static void test_strongReference_OOM() {
Bean[] beans = new Bean[SIZE];
for (int i = 0; i < beans.length; i++)
beans[i] = new Bean("strong ref " + i);
}

// no OOM
static void test_weakReference_OOM() {
@SuppressWarnings("unchecked")
Reference<Bean>[] refs = new WeakReference[SIZE];
for (int i = 0; i < refs.length; i++)
refs[i] = new WeakReference<Bean>(new Bean("weak ref " + i));
System.out.println(refs[1000].get());
}

// no OOM
static void test_softReference_OOM() {
@SuppressWarnings("unchecked")
Reference<Bean>[] refs = new SoftReference[SIZE];
for (int i = 0; i < refs.length; i++)
refs[i] = new SoftReference<Bean>(new Bean("soft ref " + i));
System.out.println(refs[1000].get());
}

// OOM
static void test_phantomReference_OOM() {
ReferenceQueue<Bean> queue = new ReferenceQueue<Bean>();
@SuppressWarnings("unchecked")
Reference<Bean>[] refs = new PhantomReference[SIZE];
for (int i = 0; i < refs.length; i++)
refs[i] = new PhantomReference<Bean>(new Bean("soft ref " + i),
queue);
}
}

class Bean {
String name;

public Bean(String name) {
this.name = name;
}

@Override
public String toString() {
return name;
}

@Override
protected void finalize() throws Throwable {
// System.out.println(name + " is finalizing at " + new Date());
}
}


参考
http://www.ibm.com/developerworks/cn/java/j-lo-langref/index.html?ca=drs-
http://zhang-xzhi-xjtu.iteye.com/blog/413159
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值