java 四种引用类型
强引用 (垃圾回收器不会回收 引用的对象)内存占满就报OOM(OutOfMemory)错误
所有的默认声明都是强引用, 想回收强引用的对象需手动将引用指向null
byte[] bytes = new byte[1024 * 1024 * 1]; //声明一个占1M内存的字节数组
bytes = null; //手动置空
设置jvm堆内存大小,测试内存溢出情况
D:\allProject\javaSE\jvm\src\four_reference>javac TestOOM.java //编译java文件
D:\allProject\javaSE\jvm\src\four_reference>cd..
//执行字节码文件并设定jvm堆内存大小 初始1M,最大2M
D:\allProject\javaSE\jvm\src>java -Xms1M -Xmx2M four_reference.TestOOM
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space //出现OOM错误 堆空间
at four_reference.TestOOM.testStrongReference(TestOOM.java:18)
at four_reference.TestOOM.main(TestOOM.java:13)
软引用 (内存够 不回收; 内存不够 回收 引用的对象)
public class TestOOM {
private static List<Object> list = new ArrayList<>();
/**
* 创建10个大小为1M的数组 每个数组对象都是一个软引用
* 将软引用添加到容器中
* 最后打印出容器内容
*/
private static void testSoftReference(){
for (int i = 0; i < 10; i++) {
//开辟字节数组并定义大小
byte[] bytes = new byte[1024 * 1024];
//软引用指向数组
SoftReference<byte[]> softReference = new SoftReference<byte[]>(bytes);
//软引用添加到容器中
list.add(softReference);
}
//通知垃圾回收器回收
//但仅是通知功能
System.gc();
for (int i = 0; i < list.size(); i++) {
Object o = ((SoftReference)list.get(i)).get(); //容器中Object类型 转化为 SoftReference类型
System.out.println(o);
}
}
public static void main(String[] args) {
testSoftReference();
}
}
当没有指定jvm内存大小时,输出为:
[B@10f87f48
[B@b4c966a
[B@2f4d3709
[B@4e50df2e
[B@1d81eb93
[B@7291c18f
[B@34a245ab
[B@7cc355be
[B@6e8cf4c6
[B@12edcd21
当指定jvm内存大小,会根据内存大小回收对象,即输出中有null
D:\allProject\javaSE\jvm\src>java -Xms4M -Xmx6M four_reference.TestOOM
//指定虚拟机初始大小为4M 最大容量为6M
输出为:
D:\allProject\javaSE\jvm\src>java -Xms4M -Xmx6M four_reference.TestOOM
null
null
null
null
null
null
null
null
[B@28a418fc
[B@5305068a //只有两个对象被保留下来
弱引用 只要垃圾回收,弱引用相关联的对象都会被回收
代码与软引用类似 只需改变类型即可
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes);
Object o = ((WeakReference)list.get(i)).get();
当执行垃圾回收时,对象全部被回收,所以输出全为:null
虚引用 引用与对象的关系最弱 永远不会通过虚引用获得对象,要与引用队列结合使用
public class PhantomReference<T> extends Reference<T> {
/**
* Returns this reference object's referent. Because the referent of a
* phantom reference is always inaccessible, this method always returns
* {@code null}.
* 虚引用是不可达的,所以总返回空
* 所以不能通过虚引用获取对象
* @return {@code null}
*/
public T get() {
return null;
}
/**
* Creates a new phantom reference that refers to the given object and
* is registered with the given queue.
* 虚引用指向的对象已经在已知队列中注册
* 空队列无意义
* @param referent the object the new phantom reference will refer to
* @param q the queue with which the reference is to be registered,
* or {@code null} if registration is not required
* 构造函数中必须指定一个引用队列
*/
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}