码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • Java的4种引用类型


            java为引用类型专门定义了一个类叫做Reference。Reference是跟java垃圾回收机制息息相关的类,通过探讨Reference的实现可以更加深入的理解java的垃圾回收是怎么工作的。

    Java中存在四种引用:

    1. StrongReference(强引用)
    2. SoftReferenc(软引用)
    3. WeakReferenc(弱引用)
    4. PhantomReference(虚引用)

    引用的结构图如下:

            ReferenceQueue引用队列是为了配合SoftReference、WeakReference、PhantomReference使用,它们三个在GC回收之前会被放到引用队列里ReferenceQueue保存下。

    1、StrongReference(强引用)

            java中的引用默认就是强引用,任何一个对象的赋值操作就产生了对这个对象的强引用。

    如:Object obj = new Object(); 

            我们new了一个Object对象,并将其赋值给obj,这个obj就是new Object()的强引用。

    强引用的特性是只要有强引用存在,被引用的对象就不会被垃圾回收。

    2、SoftReferenc(软引用)

            软引用是由java.lang.ref.SoftReference所提供的功能,意思是只有在内存不足的情况下,被引用的对象才会被回收。

    SoftReference源码如下:

    1. package java.lang.ref;
    2. public class SoftReference extends Reference {
    3. // 时间锁,由垃圾收集器更新。
    4. static private long clock;
    5. // 每次调用get方法都会更新该时间戳。JVM可能会在选择要清除的软引用时使用该字段,
    6. // 但这不是强制必须的。
    7. private long timestamp;
    8. // 返回对象的引用。如果该引用对象已经被程序或者垃圾收集器清除,则返回null。
    9. // 把最近一次垃圾回收时间赋值给timestamp
    10. public T get() {
    11. T o = super.get();
    12. if (o != null && this.timestamp != clock)
    13. this.timestamp = clock;
    14. return o;
    15. }
    16. public SoftReference(T referent) {
    17. super(referent);
    18. this.timestamp = clock;
    19. }
    20. public SoftReference(T referent, ReferenceQueuesuper T> q) {
    21. super(referent, q);
    22. this.timestamp = clock;
    23. }
    24. }

    测试代码:

    1. @Slf4j
    2. public class RefernceTest {
    3. public static void main(String[] args) {
    4. SoftReference soft = new SoftReference<>(new Object());
    5. log.info("{}",soft.get());
    6. System.gc();
    7. log.info("{}",soft.get());
    8. }
    9. }
    10. // 输出结果:
    11. 17:26:11.015 [main] INFO com.example.demo.thread.RefernceTest - java.lang.Object@68f7aae2
    12. 17:26:11.029 [main] INFO com.example.demo.thread.RefernceTest - java.lang.Object@68f7aae2
    13. 3、WeakReferenc(弱引用)

              弱引用是由java.lang.ref.WeekReference所提供的功能,不同的是weekReference引用的对象只要垃圾回收执行,就会被回收,而不管是否内存不足。

      WeekReference源码如下:

      1. package java.lang.ref;
      2. public class WeakReference extends Reference {
      3. // 创建没有注册ReferenceQueue的弱引用
      4. public WeakReference(T referent) {
      5. super(referent);
      6. }
      7. // 创建注册了ReferenceQueue的弱引用
      8. public WeakReference(T referent, ReferenceQueuesuper T> q) {
      9. super(referent, q);
      10. }
      11. }
      1. @Slf4j
      2. public class RefernceTest {
      3. public static void main(String[] args) {
      4. WeakReference weak = new WeakReference<>(new Object());
      5. log.info("{}",weak.get());
      6. System.gc();
      7. log.info("{}",weak.get());
      8. }
      9. }
      10. // 输出结果如下
      11. 17:31:40.979 [main] INFO com.example.demo.thread.RefernceTest - java.lang.Object@68f7aae2
      12. 17:31:40.998 [main] INFO com.example.demo.thread.RefernceTest - null
      13.  jdk中的弱引用代码示例:

        1. public static void main(String[] args) {
        2. ThreadLocal tl = new ThreadLocal();
        3. Object obj = new Object();
        4. tl.set(obj);
        5. tl.remove();
        6. }
        7.         当前线程的ThreadLocal中放入obj对象,key值为 创建的tl对象。 在set时,内部将使用Entry存储,Entry是弱引用,以保证在t1没有强引用的情况下,可以直接gc回收;但同时也存在一个问题,当前线程中存的obj对象的key回收后为null了,但数据还在,所以在最后需要手动的 remove,以防止内存泄露。 

          4、虚引用PhantomReference

                  虚引用是由java.lang.ref.PhantomReference所提供的关联功能。

                  作用是:跟踪垃圾回收器收集对象的活动,在GC的过程中,如果发现有PhantomReference,GC则会将引用放到ReferenceQueue中,由程序员自己处理,当程序员调用ReferenceQueue.pull()方法,将引用从ReferenceQueue移除之后,Reference对象会变成Inactive状态,意味着被引用的对象可以被回收了。

                  可以用來管理堆外不存:有些java对象关联着不归jvm管理的堆外不存,这些java对象回收时,关联的堆外内存也应该回收,回收方式为 在java对象上加虚引用,因为虚引用被回收后,会被加入到queue队列中,gc线程监控着对列,队列中有对象,则进行特殊处理。将清理掉对象关联的堆外内存。

                  PhantomReference和SoftReference和WeakReference不同的是,PhantomReference只有一个构造函数,必须传入ReferenceQueue。

          1. public class PhantomReference extends Reference {
          2. public T get() {
          3. return null;
          4. }
          5. public PhantomReference(T referent, ReferenceQueuesuper T> q) {
          6. super(referent, q);
          7. }
          8. }

          代码示例:

          1. @Slf4j
          2. public class RefernceTest {
          3. public static void main(String[] args) {
          4. Object obj = new Object();
          5. ReferenceQueue referenceQueue = new ReferenceQueue<>();
          6. PhantomReference phantomReference = new PhantomReference<>(obj,referenceQueue);
          7. log.info("{}","***************GC回收前***************");
          8. log.info("{}",obj);
          9. log.info("{}",phantomReference.get());
          10. log.info("{}",referenceQueue.poll());
          11. log.info("{}","***************启动GC***************");
          12. obj = null;
          13. System.gc();
          14. try {
          15. Thread.sleep(500); //确保GC都执行完了
          16. } catch (InterruptedException e) {
          17. e.printStackTrace();
          18. }
          19. log.info("{}",obj);
          20. log.info("{}",phantomReference.get());
          21. log.info("{}",referenceQueue.poll());
          22. }
          23. }
          24. 执行结果:

            1. 09:59:57.128 [main] INFO com.example.demo.thread.RefernceTest - ***************GC回收前***************
            2. 09:59:57.132 [main] INFO com.example.demo.thread.RefernceTest - java.lang.Object@1996cd68
            3. 09:59:57.132 [main] INFO com.example.demo.thread.RefernceTest - null
            4. 09:59:57.133 [main] INFO com.example.demo.thread.RefernceTest - null
            5. 09:59:57.133 [main] INFO com.example.demo.thread.RefernceTest - ***************启动GC***************
            6. 09:59:57.647 [main] INFO com.example.demo.thread.RefernceTest - null
            7. 09:59:57.647 [main] INFO com.example.demo.thread.RefernceTest - null
            8. 09:59:57.647 [main] INFO com.example.demo.thread.RefernceTest - java.lang.ref.PhantomReference@3339ad8e

          25. 相关阅读:
            外卖项目07---git
            拦截器
            【后台执行脚本】
            第一个 Angular 项目 - 添加路由
            Docker部署Canal监听MySQL binlog
            [flume]组成|source|channel|事务|拦截器|选择器|处理器|监控器|数据丢失问题|如何保证数据的完整性
            【Unity面试】 Lua语言基础核心 | 面试真题 | 全面总结 | 建议收藏
            【220】概率论与数理统计
            rmq消费者-推模式
            《向量数据库》——向量数据库Milvus 和大模型出联名款AI原生Milvus Cloud
          26. 原文地址:https://blog.csdn.net/weixin_40482816/article/details/126469636
            • 最新文章
            • 攻防演习之三天拿下官网站群
              数据安全治理学习——前期安全规划和安全管理体系建设
              企业安全 | 企业内一次钓鱼演练准备过程
              内网渗透测试 | Kerberos协议及其部分攻击手法
              0day的产生 | 不懂代码的"代码审计"
              安装scrcpy-client模块av模块异常,环境问题解决方案
              leetcode hot100【LeetCode 279. 完全平方数】java实现
              OpenWrt下安装Mosquitto
              AnatoMask论文汇总
              【AI日记】24.11.01 LangChain、openai api和github copilot
            • 热门文章
            • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
              奉劝各位学弟学妹们,该打造你的技术影响力了!
              五年了,我在 CSDN 的两个一百万。
              Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
              面试官都震惊,你这网络基础可以啊!
              你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
              心情不好的时候,用 Python 画棵樱花树送给自己吧
              通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
              13 万字 C 语言从入门到精通保姆级教程2021 年版
              10行代码集2000张美女图,Python爬虫120例,再上征途
            Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
            正则表达式工具 cron表达式工具 密码生成工具

            京公网安备 11010502049817号