`
天使的左手
  • 浏览: 55571 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论
阅读更多
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
分享到:
评论

相关推荐

    A Java Reference: Assorted Java Reference Material

    Your author likes to read reference manuals (believe it or not)—at least if they are reasonably complete—on the grounds that this is the most efficient way to absorb a language quickly.

    The Java Reference Library

    Java in a Nutshell Java Language Reference Java AWT Reference Java Fundamental Classes Reference Exploring Java Combined Index Combined Search Web Version Credits

    Neo4j Java Reference 3.0

    ### Neo4j Java Reference 3.0:深入理解图数据库扩展与高级应用 #### 概述 《Neo4j Java Reference 3.0》是一本详细介绍如何使用Java语言来开发和扩展Neo4j图数据库的专业指南。本书不仅覆盖了Neo4j的核心功能,...

    Java Reference Sheet

    Java reference sheet

    Java Reference源码解析

    Java Reference源码解析 Java Reference是Java语言的一种机制,用于追踪对象的可达性和垃圾回收。Java Reference源码解析主要为大家详细解析了Java Reference源码,具有一定的参考价值,感兴趣的小伙伴们可以参考...

    Java功底之Reference

    在Java编程语言中,`Reference`类是一个非常特殊且重要的概念,它超出了常规的引用类型,如`Object`或数组引用。`Reference`类及其子类主要用于处理对象的软引用、弱引用和虚引用,这些引用类型在内存管理,特别是...

    Java The Complete Reference ,11th Edition.pdf

    Java: The Complete Reference, Eleventh Edition By 作者: Herbert Schildt ISBN-10 书号: 1260440230 ISBN-13 书号: 9781260440232 Edition 版本: 11 出版日期: 2018-12-12 pages 页数: (1955) The Definitive ...

    neo4j-java-reference-3.3

    在Neo4j-java-reference-3.3这份参考指南中,涵盖了多个关于如何在Java环境中使用和扩展Neo4j数据库的高级主题。文档内容涉及到如何嵌入Neo4j到Java应用中、使用Neo4j的遍历框架、手动索引、事务管理、在线备份以及...

    Java The Complete Reference, 11th Edition 9781260440232 c.pdf

    Java The Complete Reference, 11th Edition 9781260440232 c.pdf Java The Complete Reference, 11th Edition 9781260440232 c.pdf Java The Complete Reference, 11th Edition 9781260440232 c.pdf

    Java The Complete Reference 10th Edition

    Java The Complete Reference 10th Edition Java9 编程官方参考(第10版) 带书签 文字版

    Neo4j java reference

    Neo4j的Java参考文档版本3.3详细介绍了如何在Java应用程序中嵌入Neo4j,扩展Neo4j的功能,并且介绍了如何使用REST API进行授权规则设置、远程调试配置、事务管理、手动索引、在线备份以及监控Neo4j的JMX指标。...

    Java The Complete Reference 9th

    Java自发布以来,已经经历了多个版本的迭代,目前最新的稳定版为Java 14,但本文档提及的《Java The Complete Reference 9th》涉及的Java版本是第九版对应的Java技术标准。 提到的《Java The Complete Reference 9...

    Java AWT Reference

    ### Java AWT(Abstract Window Toolkit)详解:掌握Java图形用户界面设计的核心技能 #### 引言:Java AWT——构建用户界面的基石 在Java的世界里,Abstract Window Toolkit(AWT)扮演着至关重要的角色,它为Java...

    Java之reference-JAVA程序员JAVA工程师面试必看.pdf,这是一份不错的文件

    在Java编程语言中,"reference"是一个至关重要的概念,它涉及到对象的引用和内存管理。在Java的世界里,"Everything is Object",这意味着所有的数据都以对象的形式存在,而reference则是连接这些对象与程序代码的...

    Java Reference-开源

    这将是一个Java Swing应用程序,它将用作Java API名称的快速参考。 它将具有增量搜索和过滤功能,从而提高了搜索效率。 这将是非常简单并且是统计分析Java api的好方法。

    Java+The+Complete+Reference+9+src

    《Java The Complete Reference 第九版源代码》是一个深入学习Java编程语言的重要资源。这个压缩包包含的源代码是作者在书中讲解各种Java概念和技术时所使用的示例程序,旨在帮助读者更好地理解和应用Java编程知识。...

    Java 2参考大全第31章源代码 2006年1月

    这个压缩包中的源代码文件名为"javareference",很可能是该章节所有示例的集合。 在Java编程中,源代码是用Java语言编写的程序文本,包含了类定义、方法、变量和控制流程等元素。这些源代码经过Java编译器的处理,...

    neo4j-java-reference-3.1(neo4j官方Java开发指南)

    《neo4j-java-reference-3.1》是Neo4j官方发布的针对Java开发者的详细指南,旨在帮助开发者熟练地利用Java API与Neo4j图形数据库进行交互。这本书涵盖了从安装配置到高级特性的方方面面,是Java程序员在 Neo4j 领域...

Global site tag (gtag.js) - Google Analytics