上一篇文章我们讲解了 jvm垃圾回收讲到了引用关系, 今天我们介绍一下最后两种引用关系 弱引用及虚引用
弱引用对象指那某个对象与弱引用关联,那么当JVM在进行gc垃圾回收时,无论内存是否充足,都会回收此类对象。
弱引用的应用场景
下面我们来测试一下弱引用,设置启动JVM参数
-verbose:gc -Xmx10M -Xms10M -XX:+PrintGC -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
设置JVM启动参数
创建MyFinalObj类
public class MyFinalObj {
//一般开发中不用调用这个方法
@Override
protected void finalize() throws Throwable {
System.out.println(Thread.currentThread().getName() + "\t" + "---方法调用 finalize ....");
}
}
创建测试方法
@Slf4j
public class ReferTest {
public static void main(String[] args) {
//创建弱引用
WeakReference weakReference = new WeakReference(new MyFinalObj());
log.info("-----gc before内存够用:: " + weakReference.get());
//手动GC
System.gc();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("-----gc after内存够用:: " + weakReference.get());
}
}
22:31:34.052 [main] INFO com.jzj.jvmtest.gctest.ReferTest - -----gc before内存够用:: com.jzj.jvmtest.gctest.MyFinalObj@255316f2
Finalizer ---方法调用 finalize ....
22:31:35.069 [main] INFO com.jzj.jvmtest.gctest.ReferTest - -----gc after内存够用:: null
虚引用时所有引用类型中最弱的一个,一个持有弱引用的对象,和没有引用几乎是一样的
既然这么弱,为什么还要有虚引用对象 ? 他的应用场景是什么?
虚引用的主要目的是在一个对象所占的内存被实际回收之前得到通知,从而可以进行一些相关的清理工作,主要用于检测对象是否已经从内存中删除。
创建测试类, 测试虚引用
public static void main(String[] args) throws Exception {
MyFinalObj myObj = new MyFinalObj();
ReferenceQueue objQueue = new ReferenceQueue<>();
PhantomReference prObj = new PhantomReference<>(myObj, objQueue);
//创建出来 就被回收了
log.info(String.valueOf(prObj.get()));
Thread.sleep(1000);
log.info(String.valueOf(prObj.get()));
}
执行结果, 创建完毕,对象即被回收,为null
22:50:39.682 [main] INFO com.jzj.jvmtest.gctest.ReferTest - null
22:50:40.691 [main] INFO com.jzj.jvmtest.gctest.ReferTest - null
java4种引用的级别由高到低依次为:强引用 > 软引用 > 弱引用 > 虚引用。
下面分别针对 引用类型及回收时间,应用场景做了对比如下:
引用类型 | 被垃圾回收时间 | 应用场景 | 生存时间 |
---|---|---|---|
强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时终止 |
软引用 | 当内存不足时 | 对象缓存 | 内存不足时终止 |
弱引用 | 正常垃圾回收时 | 对象缓存 | 垃圾回收后终止 |
虚引用 | 正常垃圾回收时 | 跟踪对象的垃圾回收 | 垃圾回收后终止 |
至此, Java的四种引用关系已经被我们彻底讲解完成,分别使用代码讲解了四种引用关系,下面我们开始着重开始讲解垃圾回收机制及jvm的垃圾清理机制