Java中的软引用,你了解吗?

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在Java中,垃圾回收是一个非常重要的概念。为了防止内存泄漏和程序的性能问题,Java中对于对象的垃圾回收进行了优化和改进。其中,软引用就是垃圾回收的一种方式。本文将介绍Java中的软引用,其基本概念以及如何在实际应用中使用软引用

摘要

本文将深入探讨Java中的软引用,包括其定义和使用。我们将介绍如何使用软引用来避免内存泄漏和优化程序性能。本文还将提供源代码解析,应用场景案例以及优缺点分析,以便读者更好地理解软引用的特点和使用方法。

软引用

简介

在Java中,垃圾回收是一种自动化的内存管理机制。Java垃圾回收器会自动查找不再使用的对象并将其释放回内存供重用。软引用是Java中一种机制,用于保留对对象的引用,但允许该对象被垃圾回收器回收。软引用可以帮助程序员更精细地控制内存的使用,节省程序资源并提高程序性能。

软引用对象可以通过java.lang.ref.SoftReference类创建。SoftReference对象允许程序员保留对对象的引用,但允许该对象被垃圾回收器回收。当Java虚拟机需要内存时,垃圾回收器将会回收由软引用指向的对象。软引用可以用于缓存,使得垃圾回收器在内存不足时可以回收该对象,从而避免内存泄漏。

源代码解析

下面是一个简单的Java代码例子,演示如何使用软引用:

import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        SoftReference<Object> softRef = new SoftReference<Object>(obj);
        obj = null;
        System.gc();
        if (softRef.get() != null) {
            System.out.println("Object is still available");
        } else {
            System.out.println("Object has been collected");
        }
    }
}

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  1. 创建一个Object对象,然后创建一个SoftReference对象来引用该Object对象。

  2. obj变量赋一个null值,这表示原来的Object对象已经没有指向它的引用了,只有软引用对象持有它的引用。

  3. 调用System.gc()方法,手动通知垃圾回收器回收不再使用的对象。

  4. 如果软引用对象的get()方法返回null,表示原来的Object对象已经被回收;否则,表示原来的Object对象仍然可用。

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

应用场景案例

软引用可以用于缓存、图片处理等方面,以避免内存泄漏和优化程序性能。下面是两个Java使用软引用的实际案例:

缓存

在Java中,缓存是一种常见的性能优化技术。使用软引用可以避免缓存对象过多占用内存。当内存不足时,垃圾回收器将会回收软引用指向的对象。下面是一个简单的缓存实现:

package com.example.javase.se.classes.softReference;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author ms
 * @Date 2023-11-05 21:52
 */
public class Cache {

    private Map<String, SoftReference<Object>> cacheMap;

    public Cache() {
        this.cacheMap = new HashMap<String, SoftReference<Object>>();
    }

    public void put(String key, Object value) {
        cacheMap.put(key, new SoftReference<Object>(value));
    }

    public Object get(String key) {
        Object obj = null;
        SoftReference<Object> softRef = cacheMap.get(key);
        if (softRef != null) {
            obj = softRef.get();
        }
        return obj;
    }

    public void clear() {
        cacheMap.clear();
    }
}

说明:

  1. 构造方法创建一个Map对象,用于存储软引用对象。

  2. put()方法将软引用对象添加到Map对象中。

  3. get()方法从Map对象中获取软引用对象,通过get()方法获取原始对象。

  4. clear()方法清空Map对象。

图片处理

在Java中,处理大量图片可能会导致内存泄漏和程序性能低下。使用软引用可以避免占用过多的内存,并提高程序性能。下面是一个简单的Java代码例子,演示如何使用软引用来缓存图片:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import javax.imageio.ImageIO;

public class ImageCache {
    private static final String IMAGE_DIR = "images/";
    private static Map<String, SoftReference<BufferedImage>> imageCache = new HashMap<String, SoftReference<BufferedImage>>();
    public static BufferedImage getImage(String fileName) {
        SoftReference<BufferedImage> soft = imageCache.get(fileName);
        if (soft != null) {
            BufferedImage image = soft.get();
            if (image != null) {
                return image;
            }
        }
        File file = new File(IMAGE_DIR + fileName);
        try {
            BufferedImage image = ImageIO.read(file);
            imageCache.put(fileName, new SoftReference<BufferedImage>(image));
            return image;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

说明:

  1. getImage()方法从imageCache中获取指定文件名对应的图像。如果软引用对象存在,就从软引用中获取BufferedImage对象;否则,就从磁盘中读取图像。

  2. 当软引用对象被回收时,JVM将自动从磁盘中读取图像。

优缺点分析

软引用的优点:

  1. 对象可以被垃圾回收器回收,避免内存泄漏。

  2. 可以用于缓存、图片处理等方面,以优化程序性能。

  3. 不会影响程序的正常运行。

软引用的缺点:

  1. 对象的生命周期难以控制,容易被回收。

  2. 软引用对象不能被强制保留,可能会造成性能问题。

  3. 对象被回收后,重新获取时可能会影响程序性能。

类代码方法介绍

java.lang.ref.SoftReference类

public class SoftReference<T> extends Reference<T>

该类继承自Reference类,用于创建软引用对象。可以在Java中使用该类来实现软引用。

方法:

  1. get():返回由此软引用对象所引用的对象。

Cache类

public class Cache {
    private Map<String, SoftReference<Object>> cacheMap;
    public Cache();
    public void put(String key, Object value);
    public Object get(String key);
    public void clear();
}

说明:

  1. 构造方法用于创建Cache对象,并创建一个Map对象,用于存储软引用对象。

  2. put()方法将软引用对象添加到Map对象中。

  3. get()方法从Map对象中获取软引用对象,通过get()方法获取原始对象。

  4. clear()方法清空Map对象。

ImageCache类

public class ImageCache {
    private static final String IMAGE_DIR = "images/";
    private static Map<String, SoftReference<BufferedImage>> imageCache = new HashMap<String, SoftReference<BufferedImage>>();
    public static BufferedImage getImage(String fileName);
}

说明:

  1. getImage()方法从imageCache中获取指定文件名对应的图像。如果软引用对象存在,就从软引用中获取BufferedImage对象;否则,就从磁盘中读取图像。

测试用例

下面是一个简单的测试用例,演示如何使用软引用来避免内存泄漏和优化程序性能:

public class TestSoftReference {

    public static void main(String[] args) {
        // 创建一个字符串对象并赋值"hello"
        String str = new String("hello");
        // 创建一个软引用,指向该字符串对象
        SoftReference<String> softRef = new SoftReference<String>(str);
        // 将原字符串对象引用置为null
        str = null;
        // 手动触发垃圾回收
        System.gc();
        // 判断软引用是否还指向对象
        if (softRef.get() != null) {
            System.out.println("软引用对象未被回收,内容为:" + softRef.get());
        } else {
            System.out.println("软引用对象已被回收");
        }
    }

}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

运行结果:

软引用对象未被回收,内容为:hello

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

这段代码演示了软引用的基本用法。首先创建了一个字符串对象并赋值"hello",然后创建一个软引用 softRef,指向该字符串对象。接着将原字符串对象 str 引用置为 null,这是为了让该对象成为垃圾对象。然后手动触发垃圾回收,这会触发 JVM 进行垃圾回收。

最后判断软引用是否还指向对象。如果 softRef.get() 不为 null,则说明软引用对象未被回收,打印 “软引用对象未被回收,内容为:” + softRef.get(),内容为 hello;否则说明软引用对象已被回收,打印 “软引用对象已被回收”。

可以通过改变 JVM 参数来观察软引用对象的回收情况。

SoftReference 是 JVM 提供的一种基本的引用类型,在内存充足时表现和普通强引用一样,但在内存不足时,会被 GC 回收,避免 OutOfMemoryError 异常。

继续看下一个测试用例,这次我们将创建一个缓存类来存储软引用对象:

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

public class Cache {

    private Map<String, SoftReference<Object>> cacheMap;

    public Cache() {
        cacheMap = new HashMap<>();
    }

    public void put(String key, Object value) {
        SoftReference<Object> softRef = new SoftReference<Object>(value);
        cacheMap.put(key, softRef);
    }

    public Object get(String key) {
        SoftReference<Object> softRef = cacheMap.get(key);
        if (softRef != null) {
            return softRef.get();
        }
        return null;
    }

    public void clear() {
        cacheMap.clear();
    }

}

该缓存类的实现很简单,使用Map来存储软引用对象,put()方法用于添加软引用对象,get()方法用于获取原始对象,clear()方法用于清空缓存。接下来,我们来测试该缓存类的使用:

public class TestCache {

    public static void main(String[] args) {
        // 创建一个缓存对象
        Cache cache = new Cache();
        // 缓存一个字符串对象
        String str = new String("hello");
        cache.put("str", str);
        // 将原字符串对象引用置为null
        str = null;
        // 手动触发垃圾回收
        System.gc();
        // 从缓存中获取字符串对象
        String cacheStr = (String) cache.get("str");
        // 判断缓存对象是否为空
        if (cacheStr != null) {
            System.out.println("从缓存中获取到对象:" + cacheStr);
        } else {
            System.out.println("缓存中不存在该对象");
        }
    }

}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

运行结果:

从缓存中获取到对象:hello

在这里插入图片描述

在这个示例中,我们使用Cache类来缓存一个字符串对象,并将原字符串对象的引用置为null,手动触发垃圾回收。接着,从缓存中获取字符串对象,判断缓存对象是否为空。由于该缓存对象仍然指向该字符串对象,所以从缓存中成功获取到了该对象。

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

该程序演示了使用软引用实现缓存功能。主要流程如下:

  1. 创建一个 Cache 对象,用于缓存对象。
  2. 创建一个字符串对象 “hello”,并调用 Cache 对象的 put 方法将其保存到缓存中。
  3. 将字符串对象的引用 str 置为 null。
  4. 手动触发垃圾回收,此时会触发软引用对象的回收。
  5. 从缓存中获取字符串对象并赋值给变量 cacheStr。
  6. 判断 cacheStr 是否为空,如果不为空则表示从缓存中获取到了字符串对象。

因为字符串对象被缓存后,只有缓存对象持有其软引用,当内存不足时,垃圾回收器会根据对象的引用类型及其占用内存的大小来进行垃圾回收。软引用可以在内存不足时被垃圾回收器回收,但要避免在内存足够的时候就被回收,否则就失去了缓存的意义。因此,这种方式适合缓存占用内存比较大、但不需要长时间保存的对象。

小结

软引用是Java中一种垃圾回收的方式,可以用于避免内存泄漏和优化程序性能。在Java中,可以通过SoftReference类来创建软引用对象,并可用于缓存、图片处理等方面。使用软引用可以更精细地控制内存的使用,避免内存泄漏和提高程序性能。在使用软引用时,需要注意对象的生命周期和软引用对象是否被回收。

总结

本文介绍了Java中的软引用,包括其定义、源代码解析、应用场景案例和优缺点分析。软引用是一种垃圾回收的方式,可以保留对对象的引用,但允许该对象被垃圾回收器回收,避免内存泄漏和优化程序性能。可以使用java.lang.ref.SoftReference类来创建软引用对象,并可用于缓存、图片处理等方面。需要注意对象的生命周期和软引用对象是否被回收,以便更好地控制内存的使用。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关系数据库:关系运算

文章目录 关系运算并&#xff08;Union&#xff09;差&#xff08;Difference&#xff09;交&#xff08;Intersection&#xff09;笛卡尔积&#xff08;Extended Cartesian Product&#xff09;投影&#xff08;projection&#xff09;选择&#xff08;Selection&#xff09;除…

翻译《The Old New Thing》- What a drag: Dragging a virtual file (IStream edition)

What a drag: Dragging a virtual file (IStream edition) - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080319-00/?p23073 Raymond Chen 2008年03月19日 拖拽虚拟文件&#xff08;IStream 版本&#xff09; 上一次&#xff0c;我们看…

Scikit-Learn 基础教程

目录 &#x1f40b;Scikit-Learn 基础教程 &#x1f40b;Scikit-Learn 简介 &#x1f40b; 数据预处理 &#x1f988;数据集导入 &#x1f988;数据清洗 &#x1f988;特征选择 &#x1f988;特征标准化 &#x1f40b; 模型选择 &#x1f988;分类模型 &#x1f988;回…

【 0 基础 Docker 极速入门】镜像、容器、常用命令总结

Docker Images&#xff08;镜像&#xff09;生命周期 Docker 是一个用于创建、部署和运行应用容器的平台。为了更好地理解 Docker 的生命周期&#xff0c;以下是相关概念的介绍&#xff0c;并说明它们如何相互关联&#xff1a; Docker&#xff1a; Docker 是一个开源平台&#…

HTML旋转照片盒子

效果图 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" content…

docker私有镜像仓库的搭建及认证

简介&#xff1a; docker私有镜像仓库的搭建及认证 前言 在生产上使用的 Docker 镜像可能包含我们的代码、配置信息等&#xff0c;不想被外部人员获取&#xff0c;只允许内 网的开发人员下载。 Docker 官方提供了一个叫做 registry 的镜像用于搭建本地私有仓库使用。在内部网…

C 基础 - 预处理命令和基本语法详解

#include <stdio.h> //预处理指令int main() //函数 {printf("Hello, World!"); //输出语句return 0; //返回语句 } 目录 一.预处理指令 1.#define #ifdef #ifndef #if #else #elif #endif 2.#inlcude a.新增一个文件 b.#include c.运行结果 d.扩…

Liunx中使用他人身份来执行命令或新建文件

前言 在一些情况下。我们想要借助某个用户的身份来执行命令或者新建文件&#xff0c; 比如某个用户的bash是 nologin 或者 false。 该怎么做呢&#xff1f;&#xff1f; 答&#xff1a;使用 sudo -u 即可。 例如&#xff1a; sudo -u ygz1 touch temp1.txt哈哈哈&#xff0…

【FPGA】Verilog语言从零到精通

接触fpga一段时间&#xff0c;也能写点跑点吧……试试系统地康康呢~这个需要耐心但是回报巨大的工作。正原子&&小梅哥 15_语法篇&#xff1a;Verilog高级知识点_哔哩哔哩_bilibili 1Verilog基础 Verilog程序框架&#xff1a;模块的结构 类比&#xff1a;c语言的基础…

javascript DOM 属性详解:读取、修改、移除

No.内容链接1Openlayers 【入门教程】 - 【源代码示例300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3Cesium 【入门教程】 - 【源代码图文示例200】 4MapboxGL【入门教程】 - 【源代码图文示例150】 5前端就业宝典 【面试题详细答案 1000】 文章目录 一、读取…

Tesseract-OCR使用 jTessBoxEditor 进行训练及python调用

Python-tesseract 是 python 的光学字符识别 &#xff08;OCR&#xff09; 工具。 也就是说&#xff0c;它将识别并“读取”嵌入在图像中的文本。 1、下载安装 jTessBoxEditor和tesseract-ocr 我下载的是jTessBoxEditor-2.2.0版本的&#xff0c;里面自带tesseract-ocr。 两种…

哪款桌面便签软件安全好用?2024好用便签app推荐

桌面便签软件已经成为许多人日常生活和工作中不可或缺的工具&#xff0c;它们实用、灵活&#xff0c;能够帮助我们快速记录重要信息&#xff0c;提醒任务事项。随着科技的进步&#xff0c;市面上的便签软件层出不穷&#xff0c;功能也越发强大和实用。在众多的便签软件中&#…

Linux网络-使用Tcp协议进行网络通信并通过网络接口实现远端翻译

文章目录 Tcp协议Tcp协议常见API接口1. int socket(int domain, int type, int protocol);2. int bind(int socket, const struct sockaddr *address, socklen_t address_len);struct sockaddr 3. int listen(int socket, int backlog);4. int accept(int socket, struct socka…

[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle

前言 今天给大家分享一个方便易用的.NET在线代码编辑工具&#xff0c;能够帮助.NET开发人员快速完成代码编写、测试和分享的需求&#xff08;.NET开发者的福音&#xff09;&#xff1a;.NET Fiddle。 .NET Fiddle介绍 我们可以不用再担心环境与庞大的IDE安装的问题&#xff0…

python实现——分类类型数据挖掘任务(图形识别分类任务)

分类类型数据挖掘任务 基于卷积神经网络&#xff08;CNN&#xff09;的岩石图像分类。有一岩石图片数据集&#xff0c;共300张岩石图片&#xff0c;图片尺寸224x224。岩石种类有砾岩&#xff08;Conglomerate&#xff09;、安山岩&#xff08;Andesite&#xff09;、花岗岩&am…

github有趣项目:自制“我的世界” project make

videocodehttps://www.youtube.com/watch?v4O0_-1NaWnY,https://www.bilibili.com/video/BV1oj411p7qM/?https://github.com/jdah/minecraft-weekend MAKE git clone --recurse-submodules https://github.com/jdah/minecraft-weekend.git 正克隆到 minecraft-weekend... …

【笔记】关于brew install ffmpeg出现问题解决

Macos系统需要安装ffmpeg使用&#xff0c;通过brew install ffmpeg安装相关依赖时&#xff0c;当安装至flac时出现下列问题 环境&#xff1a;有代理开启 使用国内数据源 brew install ffmpeg --verbose --debug 安装过程中显示日志 curl: (35) error:1400442E:SSL routines:C…

前端3剑客(第1篇)-初识HTML

100编程书屋_孔夫子旧书网 当今主流的技术中&#xff0c;可以分为前端和后端两个门类。 前端&#xff1a;简单的理解就是和用户打交道 后端&#xff1a;主要用于组织数据 而前端就Web开发方向来说&#xff0c; 分为三门语言&#xff0c; HTML、CSS、JavaScript 语言作用HT…

Apache Pulsar 中文社区有奖问卷调查(2024 上半年度)

Apache Pulsar 中文社区有奖问卷调查&#xff08;2024 上半年度&#xff09; &#x1f4e3; &#x1f4e3; &#x1f4e3; Hi&#xff0c;Apache Pulsar 社区的小伙伴们&#xff0c;社区 2024 上半年度的有奖问卷调查来啦&#xff01; &#x1f64c; 本次调查旨在了解用户使用 …

EIS 2019 webshell

请求中可以确定是http POST流量 同时可以判断是 蚁剑的流量 进一步过滤 http.request.method "POST" 直接追踪其tcp流 得到 列举部分 eVAl(cHr(0x40).ChR(0x69).ChR(0x6e).ChR(0x69).ChR(0x5f).ChR(0x73).ChR(0x65).ChR(0x74).ChR(0x28)直接输出一下 内容 <…