Java中的四种引用详解

6 篇文章 1 订阅
订阅专栏

Java中的四种引用

        Java中有四种引用类型:强引用、软引用、弱引用、虚引用。

强引用

        强引用是最常见的一种引用类型,在实际开发中,几乎都是强引用类型。

Object obj = new Object();

        当我们的对象有强引用的时候,即使内存不足,JVM宁愿抛出OOM,也不会把该对象回收掉。如果需要让垃圾回收器回收此对象,需要将强引用关系打破,最简单的方式就是将对象赋值为null。下面写个例子做个简单说明:

        创建一个Order对象,为了更好的知晓垃圾回收的情况,这里重写finalize()方法,因为对象被垃圾回收时都会调用此方法。

/**
 * 订单对象
 */
public class Order {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("order对象被垃圾回收");
    }
}

当对象的强引用关系被打破时,显式调用垃圾回收器

/**
 * 强引用类型垃圾回收
 */
public class NormalReferenceTest {
    public static void main(String[] args) throws IOException {
        Order order = new Order();
        // 破坏引用关系
        order = null;
        // 调用垃圾回收器,进行垃圾回收
        System.gc();
        System.out.println(order);

        // 阻塞Main主线程
        System.in.read();

    }
}

输出结果:

null
order对象被垃圾回收

根据输出结果,可知Order对象被垃圾回收掉了。

注意:

        在生产环境上,一定不要去重写finalize()方法,有内存溢出的风险。由于每个对象在进行垃圾回收时都会去调用该对象的finalize()方法,该方法默认是空的,啥都没做,执行效率是非常快的。但是如果重写后就会影响垃圾回收的效率,假设此时业务上还有大量的对象产生,垃圾回收的效率小于对象产生的效率,时间一长就会内存溢出。

软引用

软引用就是用SoftReference将引用对象包装一下,通过get()方法获取包装的对象,使用方式如下:

SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);
softReference.get();//获取软引用对象

这里用一个例子说明软引用的特点

  1. 设置堆内存大小为20M,JVM参数-Xmx20M
  2. 首先通过SoftReference包装一个byte数组,大小为10M
  3. 第一次通过get()方法获取软引用对象
  4. 调用垃圾回收器
  5. 第二次通过get()方法获取软引用对象
  6. 再次new一个byte数组,大小为12M
  7. 第三次通过get()方法回去软引用对象

代码如下:

public class SoftReferenceTest {
    public static void main(String[] args) {
        SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);// 10M
        // 获取软引用对象
        System.out.println(softReference.get());
        // 调用垃圾回收
        System.gc();
        // 睡眠一下,给与垃圾回收时间
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 再次获取软引用对象
        System.out.println(softReference.get());

        // 再new一个字节数组,堆内存不够,会触发垃圾回收,如果内存空间还不够,就会把软引用引用的对象回收掉
        byte[] bytes = new byte[1024 * 1024 * 12];// 12M
        // 再次获取软引用对象,此时将会获取为null
        System.out.println(softReference.get());
        
    }
}

运行结果:

[B@677327b6
[B@677327b6
null

说明:

        第一次获取软引用对象是有值的,接着调用GC,GC垃圾回收后,第二次获取也是有值的,说明垃圾回收时先不会回收软引用对象。随后,继续往内存里面new一个12M的byte数组,显然,我们堆内存是20M,最开始的软引用对象占10M,这里在new 一个,内存是装不下的,所以触发了垃圾回收器回收10M的软引用对象,第三次获取软引用对象时为null,因为都已被垃圾回收器回收掉了。

软引用的特点:

        当JVM进行垃圾回收时,如果第一次回收后内存足够,那么不会回收软引用对象;如果第一次回收后内存依旧不够,那么就会回收掉软引用对象。根据这个特点,软引用可以用来做缓存,当系统内存足够时,通过缓存获取值,如果内存不够时,先回收掉缓存,释放一定的内存空间,延迟OOM。

弱引用

弱引用就是通过WeakReference包装了一下,使用如下:

WeakReference<Order> weakReference = new WeakReference<>(new Order());
// 获取弱引用的值
System.out.println(weakReference.get());

弱引用和软引用最大的区别就是无论内存是否足够,弱引用都会被GC回收

/**
 * 弱引用
 */
public class WeakReferenceTest {
    public static void main(String[] args) {
        WeakReference<Order> weakReference = new WeakReference<>(new Order());
        // 获取弱引用的值
        System.out.println(weakReference.get());
        // 垃圾回收
        System.gc();
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 获取弱引用的值
        System.out.println(weakReference.get());
    }
}

运行结果:

com.test.soft.Order@677327b6
order对象被垃圾回收
null

弱引用在WeakHashMapThreadLocal中有使用到。

虚引用

Phantom 虚幻的

  • 英[ˈfæntəm]

        虚引用又叫做幻影引用,它需要配合一个队列来使用,但是我们无法通过虚引用来获取一个对象的真实引用,我们来看下面的代码

ReferenceQueue<Order> referenceQueue = new ReferenceQueue<>();

// 虚引用在垃圾回收的时候,会被放到一个队列里,这个队列供垃圾回收器做特殊处理
PhantomReference<Order> phantomReference = new PhantomReference<>(new Order(), referenceQueue);
System.out.println(phantomReference.get());// 这里输出结果为null

上述代码第五行的输出结果居然为null,进入到源码里面会发现

public class PhantomReference<T> extends Reference<T> {

    /**
     * Returns this reference object's referent.  Because the referent of a
     * phantom reference is always inaccessible, this method always returns
     * <code>null</code>.
     *
     * @return  <code>null</code>
     */
    public T get() {
        return null;
    }
}

这居然直接返回的null,虚引用不能通过get()方法获取到值,那到底有何存在的意义呢?

我们来看下面的代码:

  1. 为了演示效果,还是把堆内存大小设置为20M,添加JVM参数-Xmx20M
  2. new 一个ReferenceQueue队列,创建虚引用,将new Order(), referenceQueue作为参数传入
  3. 开启一个线程,不断的往list集合中放入数据,时间长了堆内存会满,触发垃圾回收
  4. 再开启一个线程,循环读取ReferenceQueue队列里面的值
/**
 * 虚引用
 */
public class PhantomReferenceTest {

    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        ReferenceQueue<Order> referenceQueue = new ReferenceQueue<>();

        // 虚引用在垃圾回收的时候,会被放到一个队列里,这个队列供垃圾回收器做特殊处理
        PhantomReference<Order> phantomReference = new PhantomReference<>(new Order(), referenceQueue);
        System.out.println(phantomReference.get());

        new Thread(() -> {
            while (true) {
                // 不断往list添加数据。内存会满,此时会进行垃圾回收,虚引用就会被放在队列里面
                list.add(new byte[1024 * 1024]);
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(() -> {
            while (true){
                // 从队列里面读数据
                Reference<? extends Order> poll = referenceQueue.poll();
                if (poll != null){
                    System.out.println("虚引用对象被JVM回收" + poll);
                }
            }
        }).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

输出结果:

null
null
null
null
null
null
null
null
null
null
null
null
null
order对象被垃圾回收
null
null
null
null
null
虚引用对象被JVM回收java.lang.ref.PhantomReference@12bc0828
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
	at com.test.soft.PhantomReferenceTest.lambda$main$0(PhantomReferenceTest.java:29)
	at com.test.soft.PhantomReferenceTest$$Lambda$1/1831932724.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)

虚引用特点:

        当垃圾回收器准备回收一个对象,如果发现它还有虚引用,那么就会在回收该对象之前,把这个虚引用加入到与之关联的ReferenceQueue中。在NIO中,就用了虚引用来管理堆外内存。

详解Java四种引用方式及其区别
08-26
详解Java四种引用方式及其区别 Java四种引用方式包括强引用、软引用、弱引用和虚引用,这四种引用方式是Java内存管理机制的重要组成部分。了解这些引用方式的特点和使用场景,对于Java程序的开发和优化至关...
java四种引用及在LeakCanery应用详解
08-25
Java四种引用类型是强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference),它们各自有着不同的特点和用途,主要用于内存管理和防止内存泄漏。 1. 强引用...
Java引用详解
Sweeping_Monk的专栏
08-20 286
一、对象可达性 Java虚拟机有5个不同级别的对象的可达性。 ●强可达(Strongly reachable) 如果一个对象可以被一些线程直接使用而不用通过其他引用对象(reference objects),那么它就是强可达。一个新创建的对象对创建它的线程来讲就是强可达的。 这是我们知道并且一直在使用的引用类型(译注:通常被new出来的对象都是强可达的,他们的引用就是强引用)。任何通过...
引用类型
ic_pro的博客
04-17 119
Java的对象引用主要有以下几种类型:   [b]1)强可及对象(strongly reachable)[/b]:   可以通过强引用访问的对象,一般来说,我们平时写代码的方式都是使用的强引用对象,比如下边的代码段:   StringBuilder builder= new StringBuilder();   上边代码部分引用obj这个引用引用内存堆的一个对象,这种情况下,...
java程序员应该知道的两种引用
yajie1010的专栏
11-13 162
java没有指针,到处都是引用(除了基本类型)。所以,当然,你肯定知道java引用,并用了很久,但是是不是对此了解地比较全面?而这些引用有什么作用,且有什么不同呢? Java有个java.lang.ref包,这里面都是描述引用对象的,包括了Reference,SoftReference,WeakReference和PhantomReference。其,Reference是基类其他三个类的...
Java 引用 详解
chenshun123的博客
03-11 481
Java SE2 开始,就提供了四种类型的引用 : 强引用、软引用、弱引用和虚引用Java提供这四种引用类型主要有两个目的 : 第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于 JVM 进行垃圾回收1&gt; 强引用 : 强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,JVM 宁愿抛出OutOfMemoryError 错误,使...
Java四种引用类型详细介绍
08-31
自JDK 1.2以来,Java引入了四种不同的引用级别,以提供更精细的控制权。以下是这四种引用类型的详细解释: 1. **强引用(StrongReference)** - 强引用是最常见的引用类型,例如`A a = new A()`。只要一个对象被强...
Java的对象和引用详解
08-30
"Java的对象和引用详解" Java的对象和引用详解Java编程语言两个非常重要的概念,它们之间有着紧密的联系,但同时也存在着明显的区别。为了帮助大家更好地理解对象和对象引用之间的关系,我们将从对象和对象...
Java的几种引用
qq_41655218的博客
12-17 196
从JDK1.2开始,把对象的引用分为四种级别,从而使程序能够更加灵活的控制对象的生命周期。 这四种级别由高到低依次为:强引用--&gt; 软引用--&gt;弱引用--&gt;虚引用。 强引用: 即常用的Object object = new Object();只要强引用存在,垃圾回收器就永远不会回收到此类对象。 软引用 : 用来描述一种非必需的引用对象; 软引用可用来实现内存敏感的高速...
JAVA 四种引用类型的简介说明
qq_25073223的博客
07-03 188
java四种引用类型简介说明
java引用详解_Java引用详解
weixin_42097668的博客
02-25 89
原文链接:https://blog.csdn.net/sunxianghuang/article/details/52267282https://www.cnblogs.com/yw-ah/p/5830458.html强引用(Strong Reference)强引用是指在程序代码普遍存在的,类似“Object obj=new Object()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收...
面试|JAVA 引用详解
大数据星球-浪尖
07-02 165
引用链条可以说是jvm垃圾回收的根本,而且很多编程都可以利用引用类型和jvm之间的关系来做一些系统优化。比如spark,缓存及广播变量的回收等就是采用的弱引用。本文先来介...
Java四种引用详解与使用案例
TJtulong的博客
03-15 710
Java四种引用:强引用、软引用、弱引用和虚引用 整体结构 java.lang.ref包下 强引用:Reference 软引用:SoftReference 弱引用:WeakReference 虚引用:PhantomReference 引用队列:ReferenceQueue 强引用 当内存不足时,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回...
基础知识-Java四种引用详解
qq_30878303的博客
03-20 338
0.概念虽然说很多程序猿都觉得概念啊原理啊,都是装逼用的,但是很多时候想再技术上更上一层还是得多研究研究。Java内存管理分为内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象。 Java提供这四种引用(强软弱虚)类型主要有两个作用: 第一是可以让程序员通过代码的方式决定某些对象的生命周期; 第二是有利于JVM进行垃圾回收。 1.强引用引用引用变量指向时永...
Java四种引用详解及其在LeakCanary的内存管理
本文将深入探讨Java四种引用类型:StrongReference、SoftReference、WeakReference和PhantomReference。这些引用的级别从强引用到弱引用逐渐减弱,它们在内存管理起着不同的作用,对于避免内存泄漏和优化程序...
写文章

热门文章

  • 关于Arrays.copyOfRange()方法的使用 15460
  • CentOS7中命令 ip addr 不显示IP地址的解决办法之一 8170
  • JDK各版本下载地址 2449
  • String中的substring()方法详解 1810
  • String中的charAt()方法详解 958

分类专栏

  • java基础 6篇
  • String 2篇
  • 常用注解 1篇
  • 软件下载 2篇
  • JDK 1篇
  • Tomcat 1篇
  • 微服务 2篇
  • Gateway 1篇
  • openFeign 1篇
  • linux 1篇
  • CentOS 7 2篇
  • http协议
  • eclipse相关插件
  • 设计模式
  • 算法 2篇
  • LeetCode 2篇

最新评论

  • JDK各版本下载地址

    普通网友: 文章构思巧妙,结构紧凑,既有深度又有广度,读后让人受益匪浅,确实是一篇值得一读的佳作。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • openFeign,我的时间呢?

    CSDN-Ada助手: 不知道 Java 技能树是否可以帮到你:https://edu.csdn.net/skill/java?utm_source=AI_act_java

  • openFeign,我的时间呢?

    CSDN-Ada助手: Java 技能树或许可以帮到你:https://edu.csdn.net/skill/java?utm_source=AI_act_java

  • CentOS7中命令 ip addr 不显示IP地址的解决办法之一

    公众号—程序员清宇: 感谢指正表情包 , 已修复

  • CentOS7中命令 ip addr 不显示IP地址的解决办法之一

    m0_72856711: 感谢博主,很有用 , 只是最上面那个目录是/etc吧

大家在看

  • 【linux】shell编程
  • pytorch 架构结构分析
  • SQL连续性问题:破解任意连续n问题
  • STM32F407单片机编程入门(十一) ESP8266 WIFI模块实战含源码 684
  • IIS8.0无法加载asp.net程序的解决方案

最新文章

  • String中的substring()方法详解
  • String中的charAt()方法详解
  • LeetCode - 0088 合并两个有序数组
2024年9篇
2022年2篇
2020年1篇
2019年3篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家韶关园林玻璃钢卡通雕塑玻璃钢雕塑福建玻璃钢家具雕塑造型武汉玻璃钢雕塑制作厂家潮汕玻璃钢七星瓢虫雕塑商场美陈的详细描述嘉兴玻璃钢海豚雕塑赣州赣县玻璃钢雕塑商场美陈时间温县玻璃钢雕塑加工厂家兵马俑跪姿玻璃钢雕塑价格七夕商场美陈图片济南商场美陈价钱河北周边玻璃钢花盆珠海商场玻璃钢雕塑西藏公园玻璃钢雕塑台州景区玻璃钢雕塑批发洛阳市玻璃钢雕塑维修红腹锦鸡玻璃钢雕塑商场美陈公司报价自做玻璃钢花盆湖北玻璃钢仿铜雕塑价格西安玻璃钢雕塑小品公司云浮公园摆件玻璃钢人物雕塑阜平玻璃钢雕塑公司新郑不锈钢牛玻璃钢雕塑公司厦门品质玻璃钢卡通雕塑武汉学校玻璃钢雕塑价格玻璃钢钢铁雕塑无锡玻璃钢雕塑厂家供应香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化