Java之对象引用实践

功能概述

  • 从JDK1.2版本开始,程序可以通过4种类型的对象的引用来管控对象的生命周期。这4种引用分别为,强引用、软引用、弱引用和虚引用。本文中针对各种引用做了相关测试,并做对应分析。

功能实践

场景1:弱引用、虚引用、软引用基本使用

用例代码

java 复制代码
@Test
public void test_reference_v1() {
    ReferenceQueue<Ref> queue = new ReferenceQueue<>();

    // 创建一个弱引用(指定引用的对象,以及引用对象要注册的队列)
    WeakReference<Ref> weak = new WeakReference<>(new Ref("Weak"), queue);
    // 创建一个虚引用
    PhantomReference<Ref> phantom = new PhantomReference<>(new Ref("Phantom"), queue);
    // 创建一个软引用
    SoftReference<Ref> soft = new SoftReference<>(new Ref("Soft"), queue);

    System.out.println("引用内容:");
    System.out.println(weak.get());
    System.out.println(phantom.get()); //看源码,phantom.get()始终返回null
    System.out.println(soft.get());

    System.out.println("被回收的引用:");
    for (Reference r = null; (r = queue.poll()) != null;) {
        System.out.println(r);
    }
}


class Ref {
    Object v;

    Ref(Object v) {
        this.v = v;
    }

    public String toString() {
        return this.v.toString();
    }
}

运行结果

复制代码
引用内容:
Weak
null
Soft
被回收的引用:

结果分析

  • 弱引用对象和软引用对象都是可达的,但是虚引用对象不可点,phantom.get()调用时总是为null
  • 创建弱引用、软引用、虚引用时,需要执行引用的的对象、引用对象注册的队列,如:new WeakReference<>(new Ref("Weak"), queue)

场景2:GC垃圾回收时,对象引用的行为

用例代码

java 复制代码
@Test
public void test_reference_v2() {
ReferenceQueue<Ref> queue = new ReferenceQueue<>();

WeakReference<Ref> weak = new WeakReference<>(new Ref("WeakV2"), queue); //注册:此处的Ref对象在外部没有任何引用,所以在某个时间点,GC应当回收这个对象
PhantomReference<Ref> phantom = new PhantomReference<>(new Ref("PhantomV2"), queue);
SoftReference<Ref> soft = new SoftReference<>(new Ref("SoftV2"), queue);

System.out.println("引用内容V2:");
System.out.println(weak.get());
System.out.println(phantom.get()); //看源码,phantom.get()始终返回null
System.out.println(soft.get());

System.gc();
try {
        Thread.sleep(100); //给GC留点时间,保证GC执行完成
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
}

System.out.println("被回收的引用V2:");
for (Reference r = null; (r = queue.poll()) != null; ) {
    System.out.println(r);
}

运行结果

复制代码
引用内容V2:
WeakV2
null
SoftV2
被回收的引用V2:
java.lang.ref.WeakReference@1b701da1
java.lang.ref.PhantomReference@726f3b58

结果分析

  • 弱引用和虚引用都会回收了,软引用要在接近OOM异常时回收

场景3:GC垃圾回收时,关联强引用

用例代码

java 复制代码
@Test
public void test_reference_v3() {
    ReferenceQueue<Ref> queue = new ReferenceQueue<>();

    Ref wr = new Ref("Hard"); //强引用
    WeakReference<Ref> weak = new WeakReference<>(wr, queue); //引用的对象wr是强引用
    PhantomReference<Ref> phantom = new PhantomReference<>(wr, queue);
    SoftReference<Ref> soft = new SoftReference<>(new Ref("Soft"), queue);

    System.out.println("引用内容V3:");
    System.out.println(weak.get());
    System.out.println(phantom.get());
    System.out.println(soft.get());

    System.gc();
    try {
        Thread.sleep(100); //给GC留点时间,保证GC执行完成
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.out.println("被回收的引用V3:");
    for (Reference r = null; (r = queue.poll()) != null; ) {
        System.out.println(r);
    }
}

运行结果

复制代码
引用内容V3:
Hard
null
Soft
被回收的引用V3:

结果分析

  • 弱引用、虚引用在创建时,若关联了强引用,在强引用可达时不会被回收
  • 在强引用置为null,如wr=null,表明强引用可被回收,此时关联的弱引用、虚引用都可被回收

功能总结

  • 多个引用说明:
    • a)HardReference:强引用(注:没有这个类,只是形象说明),类似String str = new String()建立起来的引用,都是强引用。在str指向另一个对象或null之前都不会被GC回收(指向另一个对象,或str=null才会被GC回收)
    • b)WeakReference:弱引用,当GC要求回收对象时,不会阻止对象被回收,即使有弱引用存在
    • c)SoftReference:软引用,当GC要求回收对象时,也不会阻止对象被回收,但回收过程会有延迟,必须要等到JVM heap内存不够用,接近产生OutOfMemory错误时,才会被回收
    • d)PhantomReference:虚引用,这种类型的引用比较特别,在大多数时间里,无法通过它拿到其引用的对象(即phantom.get()总是为null),但是,在这个对象消失的时候,该引用还是会进入ReferenceQueue队列中的
相关推荐
挺菜的5 分钟前
【算法刷题记录(简单题)003】统计大写字母个数(java代码实现)
java·数据结构·算法
掘金-我是哪吒1 小时前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
亲爱的非洲野猪1 小时前
Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
java·分布式·中间件·kafka
wfsm1 小时前
spring事件使用
java·后端·spring
微风粼粼2 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
缘来是庄2 小时前
设计模式之中介者模式
java·设计模式·中介者模式
rebel2 小时前
若依框架整合 CXF 实现 WebService 改造流程(后端)
java·后端
代码的余温3 小时前
5种高效解决Maven依赖冲突的方法
java·maven
慕y2743 小时前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba3 小时前
Maven
java·maven