Java强软弱虚四大引用

news2025/4/27 15:51:17

文章目录

  • 一、强引用
  • 二、软引用
  • 三、弱引用
  • 四、虚引用


提示:以下是本篇文章正文内容,下面案例可供参考

一、强引用

在Java中,强引用(Strong Reference)是最常见的引用类型。当我们创建一个对象并将其赋值给一个变量时,实际上就是创建了一个强引用。这意味着只要这个引用变量还存在,垃圾回收器就不会回收它所引用的对象。(除非等于null)

简单来说日常使用的大部分都是强引用,即使OOM也不回收,所以往往是导致内存泄露的元凶

代码如下(示例):

public class Test {
    public static void main(String[] args) throws Throwable {
        /**
         * 虚拟机配置选项
         * VM Options :-XX:+PrintGCDetails -Xms10m -Xmx10m
         * -XX:+PrintGCDetails:打印 GC 的详细信息
         * -Xms10m:设置初始化堆空间大小为 10m
         * -Xmx10m:设置最大堆空间大小为 10m
         */
        // 强引用
        byte[] bytes = new byte[4 * 1024 * 1024];
        // 调用 GC
        System.gc();
	}
}

输出结果(如下):

可以看出 bytes 并没有存储任何数据,仅仅是开辟空间,但是 GC 后仍然存在

在这里插入图片描述

在这里插入图片描述


二、软引用

在Java中,软引用(SoftReference)是一种特殊类型的引用,它比强引用弱,但比弱引用强。当系统内存不足时,即 JVM 空间即将耗尽,垃圾回收器会优先清理那些只被软引用关联的对象。如果一个对象只剩下软引用,那么在内存充足的情况下,该对象不会被回收;但在内存不足时,这个软引用指向的对象会被垃圾回收器回收以释放内存。
软引用通常用于实现内存敏感的缓存,例如图片缓存。当系统内存紧张时,这些缓存可以被自动清除,从而避免了 OutOfMemoryError 异常的发生,同时,在内存资源相对充足时,又能保持缓存的功能,提高程序性能。

简单来说,就是内存不足是才回收

代码如下(示例):

public class Test {
    public static void main(String[] args) throws Throwable {
        /**
         * 虚拟机配置选项
         * VM Options :-XX:+PrintGCDetails -Xms10m -Xmx10m
         * -XX:+PrintGCDetails:打印 GC 的详细信息
         * -Xms10m:设置初始化堆空间大小为 10m
         * -Xmx10m:设置最大堆空间大小为 10m
         */
        // 软引用
        Map<String, SoftReference<byte[]>> map = new HashMap<>();
        // 最大 10m 的堆空间肯定装不 24m 的数组,所以 JVM 会自动 GC 回收
        map.put("bytes1", new SoftReference<>(new byte[6 * 1024 * 1024]));
        map.put("bytes2", new SoftReference<>(new byte[6 * 1024 * 1024]));
        map.put("bytes3", new SoftReference<>(new byte[6 * 1024 * 1024]));
        // 强引用数组,无法回收
        byte[] bytes2 = new byte[6 * 1024 * 1024];
	}
}

输出结果(如下):

可以看出JVM多次调用 GC 回收软引用
在这里插入图片描述


三、弱引用

在Java中,弱引用(WeakReference)是一种特殊的引用类型,它代表的对象可被垃圾回收器在任何时候回收,即使该对象仍然有弱引用存在。相比于强引用(普通引用),只要强引用还在,垃圾回收器就不会回收该对象;而软引用和弱引用都允许在内存不足时回收其引用的对象,但软引用会在系统内存尚充足的情况下尽可能保留对象,而弱引用则不考虑当前内存状况。
弱引用的典型使用场景是在缓存或者映射关系中,当主要持有对象的强引用消失后,即使还有其他地方通过弱引用关联到这个对象,也依然会被垃圾回收器视为无用对象并进行回收。

简单来说,就是只要GC就会回收

代码如下(示例):

public class Test {
    public static void main(String[] args) {
        /**
         * 虚拟机配置选项
         * VM Options :-XX:+PrintGCDetails
         * -XX:+PrintGCDetails:打印 GC 的详细信息
         */
        // 弱引用
        // 开辟一个很小的数组
        WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[10]);
        // GC 前
        System.out.printf(Arrays.toString(weakReference.get()));
        System.out.println();
        System.gc();
        // GC 后
        System.out.printf(Arrays.toString(weakReference.get()));
        System.out.println();
    }
}

输出结果(如下):

可以看出这个很小的数组在GC后直接没了,即使空间充足

在这里插入图片描述


四、虚引用

虚引用,顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。
PhantomReference的get方法总是返回null,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入finalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理。Java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

源代码如下:

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;
    }

    /**
     * Creates a new phantom reference that refers to the given object and
     * is registered with the given queue.
     *
     * <p> It is possible to create a phantom reference with a <tt>null</tt>
     * queue, but such a reference is completely useless: Its <tt>get</tt>
     * method will always return null and, since it does not have a queue, it
     * will never be enqueued.
     *
     * @param referent the object the new phantom reference will refer to
     * @param q the queue with which the reference is to be registered,
     *          or <tt>null</tt> if registration is not required
     */
    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}

简单来说就是虚引用不存储任何东西,且必须配合引用队列使用,它唯一的作用就是监控绑定的对象是否被回收

代码如下(示例):


public class Test {
    public static void main(String[] args) {
        // 虚引用
        // 作用:监控对象的回收情况

        // 要监控的对象
        Object o1 = new Object();
        // 引用队列
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        // 虚引用绑定对象和引用队列
        PhantomReference<Object> phantomReference = new PhantomReference<>(o1, referenceQueue);

        // 回收前的被监控的对象
        System.out.println("回收前的被监控的对象: " + o1);
        // 虚引用地址
        System.out.println("虚引用地址: " + phantomReference);
        // 源码可知,总是返回 null
        System.out.println("虚引用的返回值: " + phantomReference.get());
        // 所以队列也返回 null
        System.out.println("引用队列的返回值: " + referenceQueue.poll());

        System.out.println("====================");
        // 置空监控的对象
        o1 = null;
        // 回收对象
        System.gc();
        // 监控的对象
        System.out.println("回收后的对象: " +o1);
        // 虚引用地址
        System.out.println( "虚引用地址: " + phantomReference);
        // 源码可知,总是返回 null
        System.out.println("虚引用的返回值: " + phantomReference.get());
        // 重点!!!!!
        // 引用队列中存储了虚引用,说明该对象被回收了
        // 这就是虚引用的唯一目的,即 gc 后将自身加入到引用队列
        System.out.println("引用队列的返回值: " + referenceQueue.poll());
    }
}

输出结果(如下):

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Boot整合Spring Security:构建安全的Web应用

文章目录 1. 添加依赖2. 配置Spring Security3. 创建用户服务4. 控制器和视图5. 运行应用 Spring Security是一个强大的身份验证和访问控制框架&#xff0c;用于保护Spring应用程序。它提供了全面的安全服务&#xff0c;包括身份验证、授权、攻击防护等。本文将介绍如何在Spr…

让uniapp小程序支持多色图标icon:iconfont-tools-cli

前景&#xff1a; uniapp开发小程序项目时&#xff0c;对于iconfont多色图标无法直接支持&#xff1b;若将多色icon下载引入项目则必须关注包体&#xff0c;若将图标放在oss或者哪里管理&#xff0c;加载又是一个问题&#xff0c;因此大多采用iconfont-tools工具&#xff0c;但…

原码,补码的除法

目录 一.原码的除法 &#xff08;1&#xff09;恢复余数法 重点看这 &#xff08;2&#xff09;不恢复余数法&#xff08;加减交替法&#xff09; 重点看这 二. 补码除法运算 重点看这 我们已经学习了如何进行原码&#xff0c;补码的乘法&#xff1a; http://t.csdnimg…

【代码整理】基于COCO格式的pytorch Dataset类实现

import模块 import numpy as np import torch from functools import partial from PIL import Image from torch.utils.data.dataset import Dataset from torch.utils.data import DataLoader import random import albumentations as A from pycocotools.coco import COCO …

Spring MVC精解:技术内幕与最佳实践

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天来聊聊Spring MVC&#xff0c;它是Spring的一个模块&#xff0c;专门用来构建Web应用程序。提供了一种轻量级的方式来构建动态网页。就像小黑我刚开始接触Java时候一样&#xff0c;可能对这些听起来很高…

GitHub 一周热点汇总第6期(2024/01/14-01/20)

GitHub一周热点汇总第6期 (2024/01/14-01/20) &#xff0c;梳理每周热门的GitHub项目&#xff0c;这一周的热门项目中AI的比重难得的变低了&#xff0c;终于不像一个AI热门项目汇总了&#xff0c;一起来看看都有哪些项目吧。 #1Maybe 项目名称&#xff1a;Maybe - 个人理财应…

4496 蓝桥杯 求函数零点 简单

4496 蓝桥杯 求函数零点 简单 //C风格解法1&#xff0c;通过率100% #include <bits/stdc.h> // int a, b; 一定会自动初始化为 0int main(){int a 2, b 3; // 定义a&#xff0c;b&#xff0c;不会自动初始化&#xff0c;最好自己定义时初始化// windows环境下a值固定&…

Broadcom交换芯片56620架构

文章目录 架构1.系统逻辑视图2.逻辑芯片视图3.芯片框图4.MIIM&#xff08;Medium Independent Interface Management&#xff09;5.交换结构6.CAP 架构 1.系统逻辑视图 Ingress Chip作用&#xff1a; 解析报文128字节的头部&#xff08;MMU&#xff08;Memory Management Uni…

html5实现好看的年会邀请函源码模板

文章目录 1.设计来源1.1 邀请函主界面1.2 诚挚邀请界面1.3 关于我们界面1.4 董事长致词界面1.5 公司合作方界面1.6 活动流程界面1.7 加盟支持界面1.8 加盟流程界面1.9 加盟申请界面1.10 活动信息界面 2.效果和源码2.1 动态效果2.2 源码目录结构 源码下载 作者&#xff1a;xcLei…

dpwwn:03

靶场下载 https://download.vulnhub.com/dpwwn/dpwwn-03.zip 信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-01-17 21:18 CST Stats: 0:00:00 elapsed; 0 hosts completed (0 up), 255 undergoing ARP Ping Sc…

力扣:494. 目标和(动态规划)(01背包)

题目&#xff1a; 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 ‘’ &#xff0c;在 1 之前添加…

【设计模式】什么是外观模式并给出例子!

什么是外观模式&#xff1f; 外观模式是一种结构型设计模式&#xff0c;主要用于为复杂系统、库或框架提供一种简化的接口。这种模式通过定义一个包含单个方法的高级接口&#xff0c;来隐藏系统的复杂性&#xff0c;使得对外的API变得简洁并易于使用。 为什么要使用外观模式&a…

Leetcode的AC指南 —— 栈与队列:225.用队列实现栈

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列&#xff1a;225.用队列实现栈 **。题目介绍&#xff1a;请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 …

【flutter】完全自定义样式模态对话框

示例完成结果展示&#xff1a; 示例组件代码&#xff1a; context&#xff1a;上下文 title&#xff1a;提示标题&#xff0c;null时不显示 content&#xff1a;提示内容&#xff0c;null时不显示 cancelText&#xff1a;取消按钮文字&#xff0c;null时不显示取消按钮 confirm…

Canny边缘检测 双阈值检测理解

问题引入 我们用一个实际例子来引入问题 import cv2 import numpy as npimgcv2.imread("test.png",cv2.IMREAD_GRAYSCALE) # 修改图像大小 show cv2.resize(img,(500,500))v1cv2.Canny(show,120,250) v2cv2.Canny(show,50,100)# 连接图像 res np.hstack((v1,v2)…

MSPM0L1306例程学习-UART部分(2)

MSPM0L1306例程学习系列 1.背景介绍 写在前边的话&#xff1a; 这个系列比较简单&#xff0c;主要是围绕TI官网给出的SDK例程进行讲解和注释。并没有针对模块的具体使用方法进行描述。所有的例程均来自MSPM0 SDK的安装包&#xff0c;具体可到官网下载并安装: https://www.ti…

java枚举详细解释

枚举的基本认识 我们一般直接定义一个单独的枚举类 public enum 枚举类名{枚举项1,枚举项2,枚举项3 } 可以通过 枚举类名.枚举项 来访问该枚举项的 - 可以理解为 枚举项就是我们自己定义的一个数据类型,是独一无二的 接下来我们直接用一个例子来完全理解 加深理解 这里…

[C#]winform部署openvino官方提供的人脸检测模型

【官方框架地址】 https://github.com/sdcb/OpenVINO.NET 【框架介绍】 OpenVINO&#xff08;Open Visual Inference & Neural Network Optimization&#xff09;是一个由Intel推出的&#xff0c;针对计算机视觉和机器学习任务的开源工具套件。通过优化神经网络&#xff…

vtk qt切割stl模型

一直想实现对stl模型的某个方向进行平面切割 通过滑动slider然后对模型进行某一个方向的面切割。同时可以用鼠标对模型进行移动缩放&#xff0c;旋转等操作。然后可以加一些颜色点云显示等操作。 stl加载&#xff1a; QString selectFilePath QFileDialog::getOpenFileName…

孚盟云 多处SQL注入漏洞复现

0x01 产品简介 上海孚盟软件有限公司是一家外贸SaaS服务提供商,也是专业的外贸行业解决方案专业提供商。 全新的孚盟云产品,让用户可以用云模式实现信息化管理,让用户的异地办公更加流畅,大大降低中小企业在信息化上成本,用最小的投入享受大型企业级别的信息化服务,使中…