首页 > 编程语言 >Java 四种引用类型(强引用、软引用、弱引用、虚引用)

Java 四种引用类型(强引用、软引用、弱引用、虚引用)

时间:2023-11-15 15:37:31浏览次数:35  
标签:Java Object System 引用 println 四种 o1 out

概述

Java 中的引用类似 C 语言中的指针,指向一个对象,比如:

// person 就是指向 Person 实例“张三”的引用
Person person = new Person("张三");

在 JDK1.2 以前,Java 里的引用是很传统的定义:如果 reference 类型的数据中存储的数值代表的是另外一块内存的起始地址,就称该 reference 数据是代表某块内存、某个对象的引用

这种定义当然没有什么不对,但现在看来显得太狭隘了,比如我们希望描述一类对象:当内存空间足够时,能保留在内存中,如果内存空间在进行了垃圾收集后仍然紧张,则可以抛弃这些对象,很多系统的缓存功能都符合这样的应用场景

JDK1.2 对引用的概念作了补充,将引用分为强引用(Strongly Reference)、软引用(SoftReference)、弱引用(Weak Reference)和虚引用(Phantom Reference),强度依次减弱


强引用

Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用。类似 Object obj = new Object()

当一个对象被强引用变量引用时,除非超过了引用的作用域或者显示地将相应强引用赋值为 null,否则是不可能被垃圾回收器回收的


软引用

软引用用来描述一些有用但非必须的对象,此类对象只有在进行一次垃圾收集仍然没有足够内存时,才会在第二次垃圾收集时被回收,需要用 java.lang.ref.SoftReference 类来实现

public class SoftRefenenceDemo {

    public static void main(String[] args) {
        softRefMemoryEnough();
        System.out.println("------------");
        softRefMemoryNotEnough();
    }

    private static void softRefMemoryEnough() {
        Object o1 = new Object();
        SoftReference<Object> s1 = new SoftReference<Object>(o1);
        System.out.println(o1);  // java.lang.Object@2503dbd3
        System.out.println(s1.get());  // java.lang.Object@2503dbd3

        o1 = null;
        System.gc();

        System.out.println(o1);  // null
        System.out.println(s1.get());  // java.lang.Object@2503dbd3
    }

     /**
      * JVM配置 -Xms5m -Xmx5m ,故意 new 一个大对象,使内存不足产生 OOM,看软引用回收情况
      */
    private static void softRefMemoryNotEnough() {
        Object o1 = new Object();
        SoftReference<Object> s1 = new SoftReference<Object>(o1);
        System.out.println(o1);  // java.lang.Object@4b67cf4d
        System.out.println(s1.get());  // java.lang.Object@4b67cf4d

        o1 = null;
        
        try {
          byte[] bytes = new byte[10 * 1024 * 1024];
        } catch(Error e) {
          e.printStackTrace();
        }
        

        System.out.println(o1);  // null
        System.out.println(s1.get());  // null
    }
}

弱引用

弱引用用来描述那些非必须对象,但它的强度比软引用更弱一些。被软引用关联的对象只能生存到下一次垃圾收集发生为止,当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象,需要用 java.lang.ref.WeakReference 类来实现

public class WeakReferenceDemo {

    public static void main(String[] args) {
        Object o1 = new Object();
        WeakReference<Object> w1 = new WeakReference<Object>(o1);

        System.out.println(o1);  // java.lang.Object@7440e464
        System.out.println(w1.get());  // java.lang.ref.WeakReference@49476842

        o1 = null;
        System.gc();

        System.out.println(o1);  // null
        System.out.println(w1.get());  // null
    }
}

虚引用

虚引用,顾名思义,就是形同虚设,与其他几种引用都不太一样,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列(RefenenceQueue)联合使用。虚引用的主要作用是跟踪对象垃圾回收的状态,仅仅是提供了一种确保对象被 finalize 以后,收到一个系统通知或者后续添加进一步的处理

public class PhantomReferenceDemo {

    public static void main(String[] args) throws InterruptedException {
        Object o1 = new Object();
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
        PhantomReference<Object> phantomReference = new PhantomReference<Object>(o1,referenceQueue);

        System.out.println(o1);  // java.lang.Object@7440e464
        System.out.println(referenceQueue.poll());  // null
        System.out.println(phantomReference.get());  // null

        o1 = null;
        System.gc();
        Thread.sleep(3000);

        System.out.println(o1);  // null
        System.out.println(referenceQueue.poll()); // java.lang.ref.PhantomReference@49476842
        System.out.println(phantomReference.get());  // null
    }

}

ReferenceQueue 是用来配合引用工作的,没有ReferenceQueue 一样可以运行。SoftReference、WeakReference、PhantomReference 都有一个可以传递 ReferenceQueue 的构造器。创建引用的时候,可以指定关联的队列,当 GC 释放对象内存的时候,会将引用加入到引用队列。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动,这相当于是一种通知机制。当关联的引用队列中有数据的时候,意味着指向的堆内存中的对象被回收。通过这种方式,JVM 允许我们在对象被销毁后,做一些我们自己想做的事情

标签:Java,Object,System,引用,println,四种,o1,out
From: https://www.cnblogs.com/Yee-Q/p/17833933.html

相关文章

  • CentOS中查看Java进程
    1.ps命令:可以用来查看当前系统中正在运行的进程。要查看Java进程,可以使用以下命令:ps-ef|grepjava该命令会列出所有包含“java”关键字的进程信息。你可以通过查看进程的PID(进程ID)和其他详细信息来确定你要找的java进程。2.jps命令:是Java虚拟机(JVM)提供的一个工具,用于查看当......
  • Java Mysql 类型为Long 转 前端String
    一、背景JavaMysql类型为Long转前端会丢失精度,在原先基础上补0000;二、实现1.//@JsonSerialize(using=ToStringSerializer.class)但是对我这里是不生效的@JSONField(serializeUsing=com.alibaba.fastjson.serializer.ToStringSerializer.class)生效三、遇......
  • 超音速亚原子 Java 框架来了,0.0015 秒内启动一个应用,太快了。。
    来源:juejin.cn/post/70233173515630018861、概述SpringBoot框架不用多介绍,Java程序员想必都知道。相对来说熟悉Quarkus的人可能会少一些。Quarkus首页放出的标语:超音速亚原子的Java(SupersonicSubatomicJava)。它是为OpenJDKHotSpot和GraalVM量身定制的KubernetesNative......
  • 理解与使用Javascript中的回调函数
     js里的解释:Acallbackisafunctionthatispassedasanargumenttoanotherfunctionandisexecutedafteritsparentfunctionhascompleted.    从字面上理解下来就是,回调就是一个函数的调用过程。假如函数a有一个参数,这个参数是个函数b,当函数a执行完......
  • 如何用好java的lambda表达式
    Lambda表达式是Java8引入的一种新特性,它使得在Java中能够更加方便地使用函数式编程的思想。Lambda表达式可以简洁地表示一个匿名函数,可以作为参数传递给方法或者作为返回值返回。使用Lambda表达式可以使代码更加简洁、易读,并且能够更好地利用多核处理器的优势。Lambda表达式的基本......
  • 成品直播源码,JAVA获取图片的宽、高和大小
    成品直播源码,JAVA获取图片的宽、高和大小如果是本地磁盘文件     Filefile=newFile("C:\\Users\\root\\Desktop\\test.jpg");    BufferedImagebufferedImage=ImageIO.read(newFileInputStream(file));    intheight=bufferedImage.getHei......
  • 【Windows】Java开发环境基础配置(JDK+Maven+IDEA)
    JDK下载安装包前往JDK官方网站,单击x64Installer后的下载链接,加载JDK19.0.2安装包。双击运行jdk-19_windows-x64_bin.exe。下一步,在如下步骤记录下安装路径,然后下一步直到完成。在C:\ProgramFiles\Java\jdk-19\下即可看到已安装的JDK文件。配置环境变量Windows桌面搜索......
  • Java流程控制04:if选择结构
    一、if单选择结构 二、if双选择结构 importjava.util.Scanner;publicclassifDemo02{publicstaticvoidmain(String[]args){//考试分数大于60就是及格,小于60就不及格Scannerscanner=newScanner(System.in);System.out.prin......
  • 在ARC(自动引用计数)下,IBOutlets 应该是强引用(strong)还是弱引用(weak)?
    内容来自DOChttps://q.houxu6.top/?s=在ARC(自动引用计数)下,IBOutlets应该是强引用(strong)还是弱引用(weak)?我正在使用ARC(自动引用计数)专门为iOS5进行开发。在这种情况下,指向UIView(及其子类)的IBOutlet应该是strong还是weak?以下是示例:@property(nonatomic,weak)IBO......
  • Java--day1
    一.入门1.常用快捷键ctrl+Z撤销Alt+F4关闭窗口shift+del永久删除Win+E打开我的电脑 2.基本Dos命令命令提示符ProwerShell#盘符切换 C:  #查看目录下所有内容dir#切换目录cd/df:\IDE   不同盘级之间切换 返回上一级cd.. cdabc ......