Java中的强引用、软引用、弱引用和虚引用于JVM的垃圾回收机制

2024-09-07 07:04

本文主要是介绍Java中的强引用、软引用、弱引用和虚引用于JVM的垃圾回收机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考资料

  • https://juejin.cn/post/7123853933801373733

在 Java 中,引用类型分为四种:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)。这些引用类型的主要区别在于它们如何与垃圾回收器(GC)进行交互。

1. 强引用(Strong Reference)

定义:强引用是 Java 中最常见的引用类型。只要一个对象有强引用存在,垃圾回收器就不会回收这个对象。

示例

String strongRef = new String("Hello, World!");

解释

  • 在这段代码中,strongRef 是一个指向 String 对象的强引用。只要 strongRef 变量存在,并指向 String 对象,垃圾回收器就不会回收它。

2. 软引用(Soft Reference)

定义:软引用是一个在内存不足时才会被垃圾回收的引用。它通常用于实现缓存,当内存不足时,垃圾回收器会回收这些被软引用指向的对象。

示例

import java.lang.ref.SoftReference;String str = new String("This is a soft reference example");
SoftReference<String> softRef = new SoftReference<>(str);// 使强引用失效
str = null;

解释

  • softRef 是指向 String 对象的软引用。
  • 一旦 str 置为 null,强引用消失,该对象仅通过 softRef 保持可达状态。
  • 当 JVM 发现内存不足时,它可能会回收 softRef 指向的对象。

3. 弱引用(Weak Reference)

定义:弱引用是一个比软引用更弱的引用类型。弱引用的对象在垃圾回收过程中,只要发现弱引用,不管当前内存是否足够,都会被回收。

示例

import java.lang.ref.WeakReference;String str = new String("This is a weak reference example");
WeakReference<String> weakRef = new WeakReference<>(str);// 使强引用失效
str = null;

解释

  • weakRef 是指向 String 对象的弱引用。
  • 一旦 str 置为 null,强引用消失,该对象仅通过 weakRef 保持可达状态。
  • 在下次垃圾回收时,无论内存是否充足,垃圾回收器都会回收 weakRef 指向的对象。

4. 虚引用(Phantom Reference)

定义:虚引用(或幻影引用)是最弱的一种引用类型。一个对象不能通过虚引用获得其引用对象。虚引用主要用于跟踪对象被垃圾回收的过程。当一个对象只剩下虚引用时,在下一次垃圾回收时会被回收。同时,虚引用必须和引用队列(ReferenceQueue)一起使用。

示例

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;String str = new String("This is a phantom reference example");
ReferenceQueue<String> refQueue = new ReferenceQueue<>();
PhantomReference<String> phantomRef = new PhantomReference<>(str, refQueue);// 使强引用失效
str = null;// 使用队列来检查虚引用对象是否被回收
if (phantomRef.isEnqueued()) {System.out.println("Object is ready to be reclaimed by the garbage collector.");
}

解释

  • phantomRef 是指向 String 对象的虚引用,refQueue 是一个引用队列。
  • 一旦 str 被置为 null,对象仅通过 phantomRef 虚引用保持“存在”,但实际上已经无法通过该引用访问对象。
  • 在对象被垃圾回收后,phantomRef 会被加入到 refQueue 中,程序可以通过 refQueue 得知对象已被回收。

ReferenceQueue 是 Java 中提供的一个队列,用于与软引用(SoftReference)、弱引用(WeakReference)、和虚引用(PhantomReference)等引用类型一起使用,以便在对象被垃圾回收时得到通知或做相应的清理工作。

ReferenceQueue 的作用

  1. 跟踪被回收的对象ReferenceQueue 用来保存被垃圾回收器标记为可回收的引用对象。当一个对象被垃圾回收后,如果该对象的引用(软引用、弱引用或虚引用)关联了一个 ReferenceQueue,那么这个引用会被加入到 ReferenceQueue 中。

  2. 用于清理和资源管理:通过 ReferenceQueue,程序可以在对象被回收时执行某些清理操作,例如释放外部资源、关闭文件等。特别是虚引用(PhantomReference)必须和 ReferenceQueue 一起使用,因为虚引用的主要目的是帮助检测对象的垃圾回收状态。

ReferenceQueue 的使用场景

  • 缓存管理:结合软引用和弱引用使用,在内存不足或对象无强引用的情况下,对象被垃圾回收器回收并加入到 ReferenceQueue,可用于从缓存中移除无用数据。

  • 对象的生命周期管理:对于需要明确知道对象何时被垃圾回收的场景,可以使用虚引用和 ReferenceQueue,以便在对象被回收时执行某些特殊的清理操作。

示例:使用 ReferenceQueue

下面是一个使用 ReferenceQueue 和弱引用的简单示例:

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;public class ReferenceQueueExample {public static void main(String[] args) {// 创建一个引用队列ReferenceQueue<String> refQueue = new ReferenceQueue<>();// 创建一个字符串对象并将其封装在一个弱引用中,同时关联引用队列String str = new String("Hello, ReferenceQueue");WeakReference<String> weakRef = new WeakReference<>(str, refQueue);// 清除强引用str = null;// 手动调用垃圾回收器(这只是一个提示,GC 可能不会立即执行)System.gc();// 检查引用队列中是否有被回收的引用Reference<? extends String> refFromQueue = refQueue.poll();if (refFromQueue != null) {System.out.println("The weakly referenced object has been garbage collected and the reference is in the queue.");} else {System.out.println("The object has not been garbage collected yet.");}}
}

代码解释

  1. 创建引用队列ReferenceQueue<String> refQueue = new ReferenceQueue<>(); 创建了一个 ReferenceQueue 对象,用于保存被垃圾回收的引用。

  2. 创建弱引用WeakReference<String> weakRef = new WeakReference<>(str, refQueue); 创建一个指向 str 的弱引用,并将其与 refQueue 关联。

  3. 清除强引用:通过 str = null; 清除对对象的强引用,使得该对象仅被弱引用所引用。

  4. 手动触发 GC:调用 System.gc(); 提示垃圾回收器运行。请注意,这只是一个提示,垃圾回收器不一定会立即执行。

  5. 检查引用队列:通过 refQueue.poll() 检查引用队列中是否有被回收的引用,如果返回非 null 值,则表示对象已经被回收。

总结

  • 强引用:最常见的引用类型,不会被垃圾回收。
  • 软引用:在内存不足时会被回收,适用于缓存。
  • 弱引用:在垃圾回收时会被回收,适用于对内存敏感的数据结构,如 WeakHashMap。
  • 虚引用:不能直接访问对象内容,主要用于跟踪对象的垃圾回收情况。
    在这里插入图片描述

这篇关于Java中的强引用、软引用、弱引用和虚引用于JVM的垃圾回收机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1144391

相关文章

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

SpringBoot监控API请求耗时的6中解决解决方案

《SpringBoot监控API请求耗时的6中解决解决方案》本文介绍SpringBoot中记录API请求耗时的6种方案,包括手动埋点、AOP切面、拦截器、Filter、事件监听、Micrometer+... 目录1. 简介2.实战案例2.1 手动记录2.2 自定义AOP记录2.3 拦截器技术2.4 使用Fi

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (