引用包java.lang.ref中几种引用详解 2 -- 测试代码

上一篇: 引用包java.lang.ref中几种引用详解 http://jackyin5918.iteye.com/blog/1881901

这里是一些测试代码:

测试 各个引用创建大量对象时是否导致 Heap 不足异常?

类型 是否抛出异常 示例代码 运行结果
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



清单 7

				
				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 不足的异常。


清单 8

				
				public static void main(String[] args) { 
 Reference<Bean>[] referent = new SoftReference[100000]; 
 for (int i=0;i<referent.length;i++){ 
 referent[i] = new SoftReference<Bean>(new Bean("mybean:" + i,100)); 
 } 

 System.out.println(referent[100].get());// “null”
 } 

 

总结:在新开辟 100000 个 Bean 对象时,由于软引用会视内存使用情况来判断是否自动回收,所以当最大 Heap 阈值达到 2m 时,系统自动回收最前面开辟的对象,取第 100 个对象时,返回为 null。


清单 9

				
 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。


清单 10

				
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/

你可能感兴趣的:(java)