- 引用类型及其特性
引用名称 | 特性 |
---|---|
强引用 | 普通的引用,强引用指向的对象不会被回收 |
软引用 | 仅有软引用指向对象,只有发生gc且内存不足的情况下,才会被回收 |
弱引用 | 仅有弱引用指向的对象,只要发生gc,内存就会被回收。 |
下面举个栗子说明一下:
package com.netty.demo;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public class TestDemo {
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
Object c = new Object();
Object stongRef = a;
SoftReference<Object> softReference = new SoftReference<>(b);
WeakReference<Object> weakRef = new WeakReference<>(c);
a = null;
b = null;
c = null;
System.out.println(String.format("before gc strongRef=%s,softReference=%s,weakRef=%s", stongRef, softReference.get(), weakRef.get()));
//弱应用会被gc立即回收
System.gc();
System.out.println();
System.out.println(String.format("after gc strongRef=%s,softReference=%s,weakRef=%s", stongRef, softReference.get(), weakRef.get()));
System.out.println();
//内存分配时,内存不足情况下,软引用会被回收,这里将会隐式出发一次GC
byte[] bytes = new byte[1024 * 5 * 620]
System.out.println(String.format("after gc strongRef=%s,softReference=%s,weakRef=%s", stongRef, softReference.get(), weakRef.get()));
}
}
添加VM options: -Xmx5m 运行结果:
before gc strongRef=java.lang.Object@3af49f1c,softReference=java.lang.Object@19469ea2,
weakRef=java.lang.Object@13221655
after gc strongRef=java.lang.Object@3af49f1c,softReference=java.lang.Object@19469ea2,
weakRef=null
after gc strongRef=java.lang.Object@3af49f1c,softReference=null,weakRef=null
补充说明:
-
强引用 是使用最普遍的引用,如果一个对象具有强引用,那么垃圾回收器绝不会回收它。当内存不足时,JVM宁愿抛出一个OutOfMemoryError错误,使程序异常终止。我们平时用的Object aRef = new Object();就是强引用。
-
当一个对象被JVM标记为待回收时,当前类会被注册到java.lang.ref.Finalizer类中。那么至少要经历2次gc才能真正回收掉这部分内存,这种情况一般发生在当前类或者它的父类中含有一个返回值为void的finalize的方法时,且方法内部有实现。【也就是当我们重写了finalize方法并且不是空实现时】。
对象会因为Finalizer的引用变成临时的强引用,即使没有其他强调用,还是无法立即回收。至少要等2次gc是因为只有执行完了finalize方法才有可能释放掉这个临时强引用,然后再次gc的时候才有可能被回收,实际上因为Finalizer的优先级较低,很有可能过了n次gc,对象还没有被回收掉,这个时候很可能导致对象进入到老年代【old区】进而引发old区发生gc,甚至引发Full gc,严重可导致OOM。所以你会发现很多教程对重写finalize谈的很少,因为这个方法并不是那么好用的。 -
软引用 是用来描述一些还有用但并不是必须的对象,对于软引用关联的对象,在系统发生内存溢出异常之前。将会把这写对象纳入到二次回收的范围之内进行回收,如果回收过后内存还是不足,那么就只有跑出OOM异常了。当JVM准备对这部分对象进行回收时,在调用finalize方法之前,会将SoftReference所指向的对象加入到一个ReferenceQueue对象中,这个时候我们可以通过poll方法取到他们。
-
弱引用 一般只能活过一次gc,当垃圾回收发生的时候不论内存是否还足够,都会讲这部分对象加入到一个ReferenceQueue对象中,这时我们可以通过poll方法查看它们。
-
虚引用一般是用来追踪对象被垃圾回收的状态,在对象被回收前一般会对应一个虚引用放入一个ReferenceQueue,这样可以标记那些类已经被回收过了。
网友评论