java中的四种引用

news2024/9/27 23:05:07

在java中对象的引用有强、软、弱、虚四种,这些引用级别的区别主要体现在对象的生命周期、回收时机的不同。这里在已知结论的情况下对其进行验证。

准备工作

1. 设置内存

为方便调试,将内存设置为16MB

  1. 依次点击菜单栏的Run—>Edit Configurations

    在这里插入图片描述

  2. 点击 Modify options —> Add VM option
    在这里插入图片描述

  3. 添加参数
    我这里设置的内存是16m, 对应参数为 -Xms16m -Xmx16m
    在这里插入图片描述

2. 内存检测

使用 runtime.freeMemory() 的api,用来获取到未使用内存大小

强引用

这是最常见的引用,就是平时用的"=" 赋值,当将变量指向null时则表示去除了强引用,当触发gc时变量会被回收。

public static void main(String[] args) {
	Runtime runtime = Runtime.getRuntime();
	runtime.gc();
	System.out.println("创建数组前剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
	byte[] bytes = new byte[10 * 1024 * 1024];
	System.out.println("创建数组后所用内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
	// 去除强引用
	bytes = null;
	System.gc();
	System.out.println("垃圾回收之后所用内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
}

打印结果:

创建数组前剩余内存:14.730506896972656MB
创建数组后所用内存:3.5946426391601562MB
垃圾回收之后所用内存:14.682281494140625MB

可以看出当变量bytes指向null后,调用gc将会回收byte数组。但当bytes=null后,就无法引导到byte数组。

软引用

软引用引用的变量在gc时不会被回收,只有在内存不足时才会被回收。

public static void main(String[] args) {
    Runtime runtime = Runtime.getRuntime();
    runtime.gc();
    System.out.println("创建数组前剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
    byte[] bytes = new byte[10 * 1024 * 1024];
    System.out.println("创建数组后所用内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
    SoftReference<byte[]> softReference = new SoftReference<>(bytes);
    System.out.println("添加软引用后剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
    bytes = null;
    System.out.println("弱引用的引用对象:" + softReference.get());
    System.gc();
    System.out.println("去除强引用后剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
    System.out.println("弱引用的引用对象:" + softReference.get());
    // 创建一个大于剩余内存的数组
    byte[] bigBytes = new byte[(int) (runtime.freeMemory() + 1024)];
    System.out.println("弱引用的引用对象:" + softReference.get());
}

打印结果:

创建数组前剩余内存:14.630073547363281MB
创建数组后所用内存:3.5899581909179688MB
添加软引用后剩余内存:3.5699386596679688MB
软引用的引用对象:[B@5305068a
去除强引用后剩余内存:3.66766357421875MB
软引用的引用对象:[B@5305068a
软引用的引用对象:null

当bytes = null并且gc时,byte[]并没有被回收。但在bigBytes时,由于内存不足,jvm会对软引用的对象进行回收。

弱引用

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        runtime.gc();
        System.out.println("创建数组前剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
        byte[] bytes = new byte[10 * 1024 * 1024];
        System.out.println("创建数组后所用内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
        WeakReference<byte[]> weakReference = new WeakReference<>(bytes);
        System.out.println("添加弱引用后剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
        bytes = null;
        System.out.println("弱引用的引用对象:" + weakReference.get());
        System.gc();
        System.out.println("弱引用的引用对象:" + weakReference.get());
    }
}

打印结果:

创建数组前剩余内存:14.629707336425781MB
创建数组后所用内存:3.5896987915039062MB
添加弱引用后剩余内存:3.5696792602539062MB
弱引用的引用对象:[B@5305068a
弱引用的引用对象:null

弱引用在gc触发后就会回收对象

虚引用

虚引用的创建与软引用、弱引用不同,它需要传入一个引用队列

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        runtime.gc();
        System.out.println("创建数组前剩余内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
        byte[] bytes = new byte[10 * 1024 * 1024];
        System.out.println("创建数组后所用内存:" + runtime.freeMemory() / 1024.0 / 1024 + "MB");
        ReferenceQueue<byte[]> referenceQueue  = new ReferenceQueue<>();
        PhantomReference<byte[]> phantomReference = new PhantomReference<>(bytes, referenceQueue);
        bytes = null;
        new Thread(() -> {
            while (true) {
                PhantomReference<byte[]> poll = (PhantomReference<byte[]>) referenceQueue.poll();
                if (poll != null) {
                    System.out.println("虚引用对象被回收了");
                    break;
                }
            }
        }).start();
        System.out.println("gc前虚引用的引用对象:" + phantomReference.get());
        System.gc();
        System.out.println("gc后虚引用的引用对象:" + phantomReference.get());
    }

输出:

创建数组前剩余内存:14.629470825195312MB
创建数组后所用内存:3.5897750854492188MB
gc前虚引用的引用对象:null
gc后虚引用的引用对象:null
虚引用对象被回收了:java.lang.ref.PhantomReference@618defd6

不能通过虚引用去引用对象,在gc后可以在ReferenceQueue.poll()得到虚引用

总结

创建赋值nullgc内存不足gc
强引用使用
存活
软引用使用
存活
弱引用使用
存活
虚引用使用
存活

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

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

相关文章

常用性能优化方法

在一个Java项目中进行性能优化是至关重要的。性能优化能够提高项目的效率和响应速度&#xff0c;提升用户体验&#xff0c;并且可以节省服务器资源和成本。 首先&#xff0c;性能优化可以确保项目的高效运行。当项目在运行时&#xff0c;性能问题可能会导致应用程序变慢、响应时…

Python集成测试详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 软件开发过程中&#xff0c;确保代码的稳定性和功能性至关重要。集成测试是一项关键步骤&#xff0c;旨在验证不同模块或组件能够协同工作&#xff0c;实现预期的…

信息安全工程师(22)密码学网络安全应用

前言 密码学在网络安全中的应用极为广泛且深入&#xff0c;它通过多种技术手段确保数据的机密性、完整性和真实性。 一、数据加密 对称加密&#xff1a; 定义&#xff1a;使用相同的密钥进行加密和解密的过程。特点&#xff1a;加密和解密速度快&#xff0c;适用于大数据量的加…

机器学习笔记 - week6 -(十一、机器学习系统的设计)

11.1 首先要做什么 在接下来的视频中&#xff0c;我将谈到机器学习系统的设计。这些视频将谈及在设计复杂的机器学习系统时&#xff0c;你将遇到的主要问题。同时我们会试着给出一些关于如何巧妙构建一个复杂的机器学习系统的建议。下面的课程的的数学性可能不是那么强&#xf…

一个PDF样本册免费上传网站

​随着数字化时代的到来&#xff0c;PDF样本册已经成为企业、个人展示产品、成果的重要载体。然而&#xff0c;如何高效地分享这些专业文档&#xff0c;让更多人了解和欣赏&#xff0c;成为了一个亟待解决的问题。今天让我来教你怎么制作吧 一、制作步骤 1. 注册账号&#xff…

2024京东·雪浪小镇数字科技合肥交流会

数字科技与数字经济已成为构建现代化经济体系的重要引擎。 9月22日下午,2024京东雪浪小镇数字科技合肥交流会在合肥市泓瑞金陵大酒店成功召开。本次活动由雪浪小镇未来园区与京东科技联合主办,汇聚国内数字科技行业龙头企业、雪浪小镇工业互联网重点企业以及众多高成长性创业公…

C/C++语言基础--C++运算符重载以及其重载限制

本专栏目的 更新C/C的基础语法&#xff0c;包括C的一些新特性 前言 通过前面几节&#xff0c;我们介绍了C的类与对象、构造与析构函数、拷贝、成员变量、特殊变量等相关知识&#xff0c;这一篇将详细介绍了C的运算符重载&#xff0c;我感觉这是C的一个很伟大的发明&#xff0…

[数据结构] 二叉树题目(一)

目录 一.翻转二叉树 1.1 题目 1.2 示例 1.3 分析 1.4 解决 ​编辑 二. 相同的树 2.1 题目 2.2 示例 2.3 分析 2.4 解决 三. 对称二叉树 3.1 题目 3.2 示例 3.3 分析 3.4 解决 一.翻转二叉树. - 力扣&#xff08;LeetCode&#xff09; 1.1 题目 1.2 示例 1.3 分…

猫头虎 分享已解决Bug: || Module not found: Can‘t resolve ‘react‘ 解决方案

&#x1f42f;猫头虎 分享已解决Bug&#xff1a; || Module not found: Cant resolve react 解决方案 摘要: 今天猫头虎带大家解决一个常见的前端问题&#xff0c;尤其是在 React 项目中&#xff0c;很多开发者在安装依赖包时&#xff0c;遇到过 Module not found: Cant resol…

基于大数据技术的颈椎病预防交流与数据分析及可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Mybatis详细教程 (万字详解)

Mybatis 3.5.14 来自于B站‘天气预报’,一名宝藏up,跟着他可以培养起独立解决编程问题的能力&#xff01;&#xff01;&#xff01; 01.简介 1.1 官网 官方中文网: MyBatis中文网 中文网参考手册 1.2 概念 MyBatis 是一款优秀的持久层框架&#xff0c;支持自定义 SQL, 存储过…

《强化学习的数学原理》(2024春)_西湖大学赵世钰 Ch9 策略梯度方法 9.3.2 无折扣情形下的梯度推导

v3 链接 9.3.2 无折扣情形下的梯度推导 平均奖励 r ˉ π \bar r_\pi rˉπ​ 的定义对折扣和无折扣情况都有效。在折扣情况下的梯度是一个近似值&#xff0c;它在无折扣情况下的梯度更优雅。 因为 无折扣奖励和 E [ R t 1 R t 2 R t 3 ⋯ ∣ S t s ] {\mathbb E}[…

常见框架漏洞复现

1、Thinkphp5x远程命令执行及getshell 1、环境配置 靶场:vulhub/thinkphp/5-rce docker-compose up -d 2、漏洞利用 漏洞根本源于 thinkphp/library/think/Request.php 中method方法可以进行变量覆盖&#xff0c;通过覆盖类的核心属性filter导致rce&#xff0c;其攻击点较为…

C++的vector优化

1、C中的动态数组一般是特指vector类 2、vector需要优化的原因之一是当我们push_back元素到数组中时&#xff0c;如果原来分配给动态数组的内存不够用了&#xff0c;那么就会找一块更大的内存空间分配给数组&#xff0c;把旧的内容复制到新的内存中去&#xff0c;这就是导致程…

过流会导致并联电容损坏吗

在电子元器件领域&#xff0c;电容作为重要的储能元件&#xff0c;广泛应用于电路滤波、耦合、解耦等多种场合。然而&#xff0c;当电流超过其额定容量时&#xff0c;过流现象可能对电容造成严重的损坏&#xff0c;特别是在并联电容的应用场景下。这是什么原因呢&#xff1f;一…

考研数据结构——C语言实现归并排序

包含头文件&#xff1a;程序首先包含了标准输入输出库stdio.h&#xff0c;以便使用printf等函数进行输入输出操作。 定义数组和数组大小&#xff1a;定义了一个宏N&#xff0c;其值为5&#xff0c;表示数组q的长度。数组q被初始化为{5, 3, 8, 4, 2}&#xff0c;这是我们要排序…

高性能计算应用优化实践之WRF

WRF&#xff08;Weather Research Forecast&#xff09;模式是由美国国家大气研究中心&#xff08;NCAR&#xff09;、国家环境预报中心&#xff08;NCEP&#xff09;等机构自1997年起联合开发的新一代高分辨率中尺度天气研究预报模式&#xff0c;重点解决分辨率为1&#xff5e…

Android 热点分享二维码功能简单介绍

Android 热点分享二维码 文章目录 Android 热点分享二维码一、前言二、热点二维码1、热点分享的字符串2、代码中热点字符串拼接和设置示例3、一个图片示例 三、其他1、Android 热点分享二维码小结2、Android11 设置默认热点名称和热点密码、密码长度 一、前言 比较新的Android…

智慧教育新篇章:AI如何改变英语学习方式

斯坦福大学最新发布的《2024年人工智能指数报告》指出&#xff0c;2023年全球范围内新推出的大型语言模型数量实现了翻倍增长。人工智能越来越多的被公众使用&#xff0c;并对生产力提升和就业市场产生了深远影响。作为发展新质生产力的重要引擎&#xff0c;人工智能正逐渐渗透…

React表单:formik、final-form和react-hook-form

表单无处不在&#xff0c;它是每个网站的必备部分。在用React构建web应用时&#xff0c;处理表单是不可避免的。 你可以选择自己的方式来处理&#xff0c;或者选择社区中现成的库。然而&#xff0c;当你选择一个第三方库时&#xff0c;你会立即面临一个问题&#xff1a;有太多的…