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),会对系统产生什么影响?

相关推荐
AI小码4 小时前
LLM 应用的缓存工程:当每次 API 调用都在燃烧成本
java·人工智能·spring·计算机·llm·编程·api
Hui Baby5 小时前
Spring Security
java·后端·spring
Geek-Chow6 小时前
微服务认证与授权: 12 — JWKS 深入解析
spring·微服务·安全架构
编程(变成)小辣鸡7 小时前
Spring事务失效场景
java·后端·spring
一路向北North11 小时前
Spring Security OAuth2.0(18):资源服务测试
java·后端·spring
小猿备忘录12 小时前
JVM 调优完全手册(Java 8 版)
java·开发语言·jvm
ahauedu12 小时前
多租户 RAG 知识库系统基于Spring Boot 4.0.5+Spring AI 2.0.0 + Milvus
spring·rag·springai2.0
一路向北North14 小时前
Spring Security OAuth2.0(19):JWT令牌
java·后端·spring
KobeSacre14 小时前
CyclicBarrier 源码
java·jvm·算法
卓怡学长16 小时前
w268基于springboot + vue 物流系统
java·数据库·vue.js·spring boot·spring·intellij-idea