这里是一些测试代码:
测试 各个引用创建大量对象时是否导致 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
|
总结:在新开辟 100000 个 Bean 对象时,由于强引用永远不会被系统回收,当最大 Heap 阈值达到 2m 时,系统就会报出 Heap 不足的异常。
清单 8
|
总结:在新开辟 100000 个 Bean 对象时,由于软引用会视内存使用情况来判断是否自动回收,所以当最大 Heap 阈值达到 2m 时,系统自动回收最前面开辟的对象,取第 100 个对象时,返回为 null。
清单 9
|
总结:WeakReference 与 SoftReference 具有相同的特性,也会视内存使用情况来判断是否自动回收。取第 100 个对象时,返回为 null。
清单 10
|
总结: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);
}
}
}