上一篇: 引用包java.lang.ref中几种引用详解 http://jackyin5918.iteye.com/blog/1881901
这里是一些测试代码:
类型 是否抛出异常 示例代码 运行结果StrongReference | 抛出异常 | 见清单 6 | Exception in thread "main" java.lang.OutOfMemoryError: Java heap space |
SoftReference | 不抛异常,之前的引用自动清空并返回 null | 见清单 7 | null |
WeakReference | 同上 | 见清单 8 | null |
PhantomReference | 抛出异常 | 见清单 9 | Exception in thread "main" java.lang.OutOfMemoryError: Java heap space |
public static void main(String[] args) { Bean[] referent = new Bean[100000]; for (int i=0;i<referent.length;i++){ referent[i] = new Bean("mybean:" + i,100);// 抛 Exception } } |
总结:在新开辟 100000 个 Bean 对象时,由于强引用永远不会被系统回收,当最大 Heap 阈值达到 2m 时,系统就会报出 Heap 不足的异常。
总结:在新开辟 100000 个 Bean 对象时,由于软引用会视内存使用情况来判断是否自动回收,所以当最大 Heap 阈值达到 2m 时,系统自动回收最前面开辟的对象,取第 100 个对象时,返回为 null。
public static void main(String[] args) { Reference<Bean>[] referent = new WeakReference[100000]; for (int i=0;i<referent.length;i++){ referent[i] = new WeakReference<Bean>(new Bean("mybean:" + i,100)); } System.out.println(referent[100].get());// “null” } |
总结:WeakReference 与 SoftReference 具有相同的特性,也会视内存使用情况来判断是否自动回收。取第 100 个对象时,返回为 null。
public static void main(String[] args) { Reference<Bean>[] referent = new PhantomReference[100000]; ReferenceQueue<Bean> queue = new ReferenceQueue<Bean>(); for (int i=0;i<referent.length;i++){ referent[i] = new PhantomReference<Bean>(new Bean("mybean:" + i,100), queue);// throw Exception } System.out.println(referent[100].get()); } |
总结:PhantomReference 类似强引用,它不会自动根据内存情况自动对目标对象回收,所以这里在 Heap 里不断开辟新空间,当达到 2m 阈值时,系统报出 OutOfMemoryError 异常。
自己的测试代码:
a.强引用,内存不足时异常,OutOfMemory
package test.reference; /** * 测试强引用 * 总结:在新开辟 10000000 个 Bean 对象时,由于强引用永远不会被系统回收, * 当最大 Heap 阈值达到 5m 时,系统就会报出 Heap 不足的异常。 * * 创建大量对象,这里在myeclipse中将JVM的参数设置为 -Xmx5m -Xms5m(能设置的最小内存了,再小就报错了) * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space * at test.reference.TestCommonReference.main(TestCommonReference.java:17) * */ public class TestCommonReference { public static void main(String[] args) { int iCount = 10000000; Bean[] beans = new Bean[iCount]; for (int i=0;i<iCount;i++) { beans[i] = new Bean("Jack-"+i,i); } } }
b. 软引用测试
package test.reference; import java.lang.ref.Reference; import java.lang.ref.SoftReference; /** * 软引用使用 get() 方法取得对象的强引用从而访问目标对象。 * 软引用所指向的对象按照 JVM 的使用情况(Heap 内存是否临近阈值)来决定是否回收。 * 软引用可以避免 Heap 内存不足所导致的异常。 * * 创建大量对象,这里在myeclipse中将JVM的参数设置为 -Xmx5m -Xms5m(最小内存了,再小就报错了) * */ public class TestSoftReferenceM { public static void main(String[] args) { int iCount = 1000000; /** * 当iCount取10万时,程序正常,references[100].get()为null,因为当heap内存不够是SoftReference对象自动被回收了, * 这里显然references[100]的软引用对象被回收了 * 但,当iCount取100万时, * 程序也报异常:OutOfMemoryError: Java heap space * 这里是因为references数组太大了,而每一个references元素是一个SoftReference<Bean>对象,这个是强引用,不能释放 */ Reference<Bean>[] references = new SoftReference[iCount];//不能创建泛型数组,所以new SoftReference<Bean>[iCount];//错误 for(int i=0;i<iCount;i++) { references[i] = new SoftReference<Bean>(new Bean("Jack_" + i,i)); } System.out.println(references[100].get()); } }
c:弱引用
package test.reference; import java.lang.ref.Reference; import java.lang.ref.WeakReference; /** * 总结:WeakReference 与 SoftReference 具有相同的特性, * 也会视内存使用情况来判断是否自动回收。取第 100 个对象时,返回为 null。 * * 弱引用所指向的对象只要进行 GC,就会自动进行回收,get() 返回 null。 * 弱引用使用 get() 方法取得对象的强引用从而访问目标对象。 * 一旦系统内存回收,无论内存是否紧张,弱引用指向的对象都会被回收。 * 弱引用也可以避免 Heap 内存不足所导致的异常。 * * 创建大量对象,这里在myeclipse中将JVM的参数设置为 -Xmx5m -Xms5m(最小内存了,再小就报错了) * */ public class TestWeakReferenceM { public static void main(String[] args) { int iCount = 100000; /** * 当iCount取10万时,程序正常,references[100].get()为null,因为当heap内存不够是SoftReference对象自动被回收了, * 这里显然references[100]的软引用对象被回收了 * 但,当iCount取100万时, * 程序也报异常:OutOfMemoryError: Java heap space * 这里是因为references数组太大了,而每一个references元素是一个SoftReference<Bean>对象,这个是强引用,不能释放 */ Reference<Bean>[] references = new WeakReference[iCount];//不能创建泛型数组,所以new SoftReference<Bean>[iCount];//错误 for(int i=0;i<iCount;i++) { references[i] = new WeakReference<Bean>(new Bean("Jack_" + i,i)); } System.out.println(references[100].get()); } }
d:虚引用
package test.reference; import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; /** * 虚引用有以下特征: * 虚引用永远无法使用 get() 方法取得对象的强引用从而访问目标对象。 * 虚引用所指向的对象在被系统内存回收前,虚引用自身会被放入 ReferenceQueue 对象中从而跟踪对象垃圾回收。 * 虚引用不会根据内存情况自动回收目标对象。 * 另外值得注意的是,其实 SoftReference, WeakReference 以及 PhantomReference 的构造函数都可以接收一个 ReferenceQueue 对象。 * 当 SoftReference 以及 WeakReference 被清空的同时,也就是 Java 垃圾回收器准备对它们所指向的对象进行回收时, * 调用对象的 finalize() 方法之前,它们自身会被加入到这个 ReferenceQueue 对象中, * 此时可以通过 ReferenceQueue 的 poll() 方法取到它们。 * 而 PhantomReference 只有当 Java 垃圾回收器对其所指向的对象真正进行回收时, * 会将其加入到这个 ReferenceQueue 对象中,这样就可以追综对象的销毁情况。 * * 总结:PhantomReference 类似强引用,它不会自动根据内存情况自动对目标对象回收, * 所以这里在 Heap 里不断开辟新空间,当达到 5m 阈值时,系统报出 OutOfMemoryError 异常。 * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space * */ public class TestPhantomReferenceM { public static void main(String[] args) { ReferenceQueue<Bean> refQueue = new ReferenceQueue<Bean> (); int iCount = 100000; PhantomReference<Bean>[] referents = new PhantomReference[iCount]; for(int i=0;i<iCount;i++) { referents[i] = new PhantomReference<Bean>(new Bean("Jack_"+i,i),refQueue); } } }
参考
深入探讨 java.lang.ref 包 http://www.ibm.com/developerworks/cn/java/j-lo-langref/