`
nathan09
  • 浏览: 155419 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Java中WeakReference、WeakHashMap、SoftReference、ReferenceQueue的作用和使用场景

 
阅读更多
详见以下测试代码及其注释:

package test;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;

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.Map;
import java.util.WeakHashMap;

import org.junit.Test;

class VeryBig {
	private static final int	SIZE	= 1000;
	private double[]		la	= new double[SIZE];
	private String			ident;

	public VeryBig(String id) {
		ident = id;
	}

	public VeryBig(String id, int s) {
		ident = id;
		la = new double[s];
	}

	public String toString() {
		return ident;
	}

	protected void finalize() {
		System.out.println("Finalizing " + ident);
	}
}

public class ReferencesTest {
	/**
	 * Strong Reference<br>
	 * 是 Java 的默认引用实现, 它会尽可能长时间的存活于 JVM 内, 当没有任何强引用指向对象时, GC 执行后将会回收对象
	 */
	@Test
	public void strongReferenceNotGC() {
		System.out.println("start test strongReferenceNotGC");
		Object referent = new VeryBig("strongReferenceNotGC");

		/**
		 * 通过赋值创建 StrongReference
		 */
		Object strongReference = referent;

		assertSame(referent, strongReference);

		referent = null;
		System.gc();

		/**
		 * 由于对象还存在引用,因此gc后,对象未被回收
		 */
		assertNotNull(strongReference);
		System.out.println("end test strongReferenceNotGC");
	}

	@Test
	public void strongReferenceGC() throws InterruptedException {
		System.out.println("start test strongReferenceGC");
		Object referent = new VeryBig("strongReferenceGC");
		referent = null;
		System.gc();
		Thread.sleep(500);
		System.out.println("end test strongReferenceGC");
	}

	/**
	 * WeakReference<br>
	 * 顾名思义, 是一个弱引用, 当所引用的对象在 JVM 内不再有强引用时, GC后,弱引用被置成null,并回收所指的对象
	 * 
	 * @throws InterruptedException
	 */
	@Test
	public void weakReference() throws InterruptedException {
		System.out.println("start test weakReference");
		WeakReference<Object> weakRerference = new WeakReference<Object>(new VeryBig(
				"weakReference"));
		System.gc();
		Thread.sleep(500);
		/**
		 * weak reference 在 GC 后会被置成null,对象就可以被 回收了。。。
		 */
		assertNull(weakRerference.get());
		System.out.println("end test weakReference");
	}

	/**
	 * WeakHashMap<br>
	 * 使用 WeakReference 作为 key, 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的
	 * entry
	 * 
	 * @throws InterruptedException
	 */
	@Test
	public void weakHashMap() throws InterruptedException {
		Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();
		Object key = new VeryBig("weakHashMap key");
		Object value = new Object();
		weakHashMap.put(key, value);

		assertTrue(weakHashMap.containsValue(value));

		key = null;
		System.gc();
		/**
		 * 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理
		 */
		Thread.sleep(1000);

		/**
		 * 一旦没有指向 key 的强引用, WeakHashMap 在 GC 后将自动删除相关的 entry
		 */
		assertFalse(weakHashMap.containsValue(value));
	}

	/**
	 * SoftReference<br>
	 * 与 WeakReference 的特性基本一致, 最大的区别在于
	 * SoftReference会尽可能长的保留引用,不会在GC时就回收对象,而是直到 JVM 内存不足时才会被回收(虚拟机保证),
	 * 这一特性使得 SoftReference 非常适合缓存应用
	 */
	@Test
	public void softReference() {
		SoftReference<Object> softRerference = new SoftReference<Object>(new VeryBig(
				"softReference"));

		assertNotNull(softRerference.get());

		System.gc();

		/**
		 * soft references 只有在 jvm OutOfMemory 之前才会被回收, 所以它非常适合缓存应用
		 */
		assertNotNull(softRerference.get());

		// make oom....
		int i = 0;
		while (true) {
			try {
				++i;
				new VeryBig("oom ", 10000000);
			} catch (Throwable e) {
				System.out.println("OOM after " + i + " times");
				e.printStackTrace();
				break;
			}
		}

		assertNull(softRerference.get());
	}

	/**
	 * PhantomReference<br>
	 * Phantom Reference(幽灵引用) 与 WeakReference 和 SoftReference 有很大的不同, 因为它的
	 * get() 方法永远返回 null, 这也正是它名字的由来
	 */
	@Test
	public void phantomReferenceAlwaysNull() {
		ReferenceQueue<Object> q = new ReferenceQueue<Object>();
		PhantomReference<Object> phantomReference = new PhantomReference<Object>(
				new VeryBig("phantomReferenceAlwaysNull"), q);

		/**
		 * phantom reference 的 get 方法永远返回 null
		 */
		assertNull(phantomReference.get());

		assertNull(q.poll());
		System.gc();
		assertNull(q.poll());
	}

	/**
	 * RererenceQueue<br>
	 * 当一个 WeakReference 开始返回 null 时, 它所指向的对象已经准备被回收, 这时可以做一些合适的清理工作. 将一个
	 * ReferenceQueue 传给一个 Reference 的构造函数, 当对象被回收时, 虚拟机会自动将这个weak ref插入到
	 * ReferenceQueue 中, WeakHashMap 就是利用 ReferenceQueue 来清除 key 已经没有强引用的
	 * entries
	 * 
	 * @throws InterruptedException
	 */
	@Test
	public void referenceQueueWithWeakReference() throws InterruptedException {
		Object referent = new VeryBig("referenceQueueWithWeakReference");
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
		Reference<Object> ref = new WeakReference<Object>(referent, referenceQueue);

		assertFalse(ref.isEnqueued());
		Reference<? extends Object> polled = referenceQueue.poll();
		assertNull(polled);

		referent = null;
		System.gc();

		assertTrue(ref.isEnqueued());
		Reference<? extends Object> removed = referenceQueue.remove();
		assertNotNull(removed);
		assertSame(ref, removed);
		assertNull(removed.get());
	}

	@Test
	public void referenceQueueWithSoftReference() throws InterruptedException {
		Object referent = new VeryBig("referenceQueueWithWeakReference");
		ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
		Reference<Object> ref = new SoftReference<Object>(referent, referenceQueue);

		assertFalse(ref.isEnqueued());
		Reference<? extends Object> polled = referenceQueue.poll();
		assertNull(polled);

		referent = null;
		// make oom....
		try {
			new VeryBig("oom ", 100000000);
		} catch (Throwable e) {

		}
		assertTrue(ref.isEnqueued());
		Reference<? extends Object> removed = referenceQueue.remove();
		assertNotNull(removed);
		assertSame(ref, removed);
		assertNull(removed.get());
	}
}


参考:

http://www.iteye.com/topic/401478

http://zhang-xzhi-xjtu.iteye.com/blog/484934

http://zhang-xzhi-xjtu.iteye.com/blog/413159

分享到:
评论

相关推荐

    SoftReference、WeakReference和PhantomRefrence分析和比较

    SoftReference、WeakReference和PhantomReference分析和比较 在 Java 中,引用类型分为强引用、软引用、弱引用和虚引用四种。强引用是我们最常用的引用类型,而软引用、弱引用和虚引用则是 Java 为我们提供的三种...

    StrongReference,SoftReference, WeakReference的使用实例

    StrongReference,SoftReference, WeakReference的使用实例,请参照博客:http://blog.csdn.net/To_be_Designer/article/details/72673421

    Java引用总结--StrongReference、SoftReference、WeakReference、PhantomRef

    软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 弱引用(WeakReference)弱引用与软引用的区别在于:只...

    Java编程WeakHashMap实例解析

    在WeakHashMap中,每个键和值都是WeakReference对象,这样可以使得垃圾回收器自动清理键和值。 在WeakHashMap的put方法中,会使用WeakReference来包装键和值,这样可以使得垃圾回收器自动清理键和值。在put方法中,...

    Java中内存泄露及垃圾回收机制参照.pdf

    4. 使用WeakReference和SoftReference,WeakReference和SoftReference可以帮助避免内存泄漏。 Java的垃圾回收机制可以自动回收内存中的垃圾,避免内存泄漏,但是程序员需要注意避免内存泄漏的几点,以确保程序的...

    解决 Java 内存泄漏的十大实战技巧与应用

    具体包括使用 WeakReference 和 SoftReference 管理对象引用、利用 Cleaner 进行资源清理、监控引用链、使用内存分析工具、检查集合类、清理 ThreadLocal 和静态引用、监控 JVM 内存使用、检测对象生命周期以及进行...

    WeakHashMap的使用方法详解

    1. WeakHashMap 的使用场景:WeakHashMap 通常用于缓存和内存管理,在缓存中,它可以自动地清除无用的缓存对象,从而避免了内存泄露。 2. WeakHashMap 的实现机理:WeakHashMap 的实现是基于 WeakReference 的, ...

    详解Java弱引用(WeakReference)的理解与使用

    Java 中的弱引用(WeakReference)是一种特殊的引用类型,它可以帮助我们更好地管理内存和避免内存泄漏。在 Java 中,当一个对象被创建时,它被放在堆(Heap)中。当垃圾回收器(GC)运行时,如果发现没有任何引用...

    详解Java对象的强、软、弱和虚引用+ReferenceQueue

    软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 三、弱引用(WeakReference) 弱引用与软引用的区别...

    Java中的软引用弱引用和虚引用.docx

    ### Java中的软引用、弱引用和虚引用详解 #### 一、引言 在Java开发过程中,特别是Android应用开发中,经常会遇到一个普遍的问题——内存溢出(OutOfMemory Error,简称OOM)。这个问题往往与如何有效地管理内存...

    《Effective Java》读书分享.pptx

    消除过期引用可以使用多种方法,例如,使用 WeakReference 或 SoftReference,或者使用 finalize() 方法来回收对象。 其他知识点 其他知识点还包括泛型、枚举和注解、Lambda 和 Stream、方法、通用编程、异常、...

    很容易弄错的java面试题

    面试官可能会让你解释 finalize() 方法的作用,以及何时应该使用 WeakReference 或 SoftReference。 7. **接口与抽象类**:两者之间的选择,以及Java 8引入的默认方法(default methods)如何改变这一格局。接口...

    用java代码实现的移除未使用资源。.zip

    有时我们希望对象在被垃圾回收之前保留一段时间,这时可以使用`WeakReference`和`SoftReference`。`WeakReference`的对象只要没有任何强引用指向它,就会被GC回收;而`SoftReference`的对象会在系统内存不足时才会被...

    Java中弱引用软引用虚引用及强引用的区别Java开发Ja

    在Java开发中,熟练掌握这些引用类型的概念和使用场景,可以帮助我们编写出更加高效、健壮的代码。同时,理解垃圾收集的工作原理也非常重要,因为这直接影响到程序的性能和稳定性。在实际开发中,合理利用这些引用...

    00M原因以及分析处理

    5. 使用WeakReference和SoftReference: WeakReference和SoftReference可以帮助开发者更好地管理应用程序中的对象生命周期。 OOM错误的常见解决方法 1. 使用System.gc():System.gc()可以强制垃圾回收器回收垃圾...

    java 数据库实现(设计模拟DBMS)

    - 为了提高性能,可以引入缓存机制,如使用Java的WeakReference、SoftReference,或者引入第三方缓存框架如Redis或Memcached。 9. **分布式数据库**: - 高可用性和扩展性要求数据库可能需要分布式部署,Java的...

    JVM 77 道面试题及答案.docx

    4. WeakReference 与 SoftReference: WeakReference 和 SoftReference 都可以用于提高 GC 和内存的效率,但是 WeakReference 一旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到...

    9套android经典面试题

    - WeakReference和SoftReference的区别及使用场景。 5. **数据存储** - SharedPreference、SQLite数据库、内部/外部存储的使用。 - ContentProvider的理解和使用,以及它在跨应用数据共享中的作用。 6. **网络...

    Java内存泄露及内存无法回收解决方案

    3. 使用弱引用和软引用:在某些场景下,可以使用WeakReference或SoftReference,让对象在需要时可以被GC回收。 4. 优化单例模式:确保单例对象在不再需要时能被正确清理。 5. 限制静态集合类大小:避免无限增长的...

Global site tag (gtag.js) - Google Analytics