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

相关文章

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2