Bean 会被 JVM 回收吗?

文章目录

核心结论:会,但前提是它必须变得"不可达"。

Bean 本质上就是堆内存里的一个普通的 Java 对象。JVM 的垃圾回收(GC)逻辑对它依然生效,但 Spring 容器(ApplicationContext)的存在直接干预了它的"生命长度"。


1. Singleton Bean(单例):通常与容器同生死

对于单例 Bean,JVM 回收它的阻碍在于 Spring 容器本身

  • 强引用的拉扯 :Spring 容器内部维护着一个单例池(通常是一个 ConcurrentHashMap),用来存放所有的单例 Bean 实例。
  • GC 路径 :在 JVM 的 GC 算法(如可达性分析)中,ApplicationContext 通常作为一个 GC Root 或者被 GC Root 引用。只要容器还在运行,它就一直"拉着"这些 Bean 的引用。
  • 回收时机只有当容器被关闭(Close)时,容器才会清空单例池,释放对这些 Bean 的引用。此时,如果没有其他业务代码(比如静态变量)还拽着这个 Bean,它才会变成"垃圾",在下一次 GC 时被清理。

2. Prototype Bean(多例):管生不管死

多例 Bean 的待遇和单例完全不同:

  • Spring 的放手 :Spring 容器只负责多例 Bean 的创建、初始化和装配。一旦它把这个对象交到你手中,它就不再持有这个对象的任何引用了。
  • 回收时机 :它就像你直接 new 出来的普通对象一样。一旦你的业务逻辑执行完毕,不再有任何变量指向它,它就会立即变成不可达状态,静候 JVM 的 GC 回收。

3. 决定 Bean 被回收的具体条件

一个 Spring Bean 要想被 JVM 回收,必须同时满足以下两个"断开":

  1. Spring 容器断开引用
  • 对于单例:必须销毁容器或手动从容器中剔除 Bean。
  • 对于多例:创建完成即已断开。
  1. 业务代码断开引用
  • 如果你在代码里把一个 Bean 赋值给了一个静态变量(Static) ,或者放进了一个长生命周期的集合 里,那么即使 Spring 容器关了,JVM 依然无法回收它。这就是常见的内存泄漏来源。

总结对照表

Bean 作用域 Spring 容器是否持有引用 谁决定它何时被回收?
Singleton 是(存放在单例缓存池中) Spring 容器。容器关闭,引用才释放。
Prototype 否(创建完就撒手) 你的代码。你不用了,它就被回收。

一句话总结:

Bean 只是披着 Spring 外壳的对象,能不能回收,全看 JVM 的引用链上还有没有它的位置。单例 Bean 就像是住进了"养老院"(容器),只要养老院不倒闭,它就一直活着。

既然说到单例 Bean 很难被回收,你觉得如果在单例 Bean 里面定义了一个巨大的成员变量(比如一个装了几百万条数据的 ArrayList),会对系统产生什么影响?

相关推荐
逻极16 小时前
Java 从入门到精通:核心原理、最佳实践与性能优化
java·jvm·并发编程·集合框架
摇滚侠16 小时前
SpringBoot 内嵌 TongWeb 东方通替换 Tomcat
java·spring boot·spring
代码旅人ing17 小时前
Redis+Spring+MyBatis + 微服务 + 消息队列核心知识点(面试高频题目合集)
redis·spring·mybatis·java-rabbitmq
light blue bird17 小时前
Razor Pages工序管理Web端界面化实现方案
jvm·windows·web端
仙俊红17 小时前
spring有多个对象时如何注入
java·后端·spring
架构源启18 小时前
Spring AI进阶系列(13)- 安全最佳实践(进阶版):Prompt注入防护、数据泄露预防与合规审计实战
人工智能·安全·spring
REDcker18 小时前
Linux文件IO底层原理详解
linux·运维·spring
霸道流氓气质18 小时前
Spring AI Alibaba 学习路线图:从入门到精通
人工智能·学习·spring
闪电悠米18 小时前
黑马点评-优惠券秒杀-03_basic_seckill_and_oversell
java·数据库·spring boot·spring·缓存·oracle·面试
.Cnn19 小时前
MySQL事务和Spring事务
数据库·后端·mysql·spring