成员变量不被单独回收,真正回收的是其指向的对象;对象能否被回收取决于是否仍被强引用可达,尤其是否被存活对象的成员变量持有。

成员变量本身不被垃圾回收,真正被回收的是它所指向的对象;而该对象能否被回收,取决于它是否还被任何强引用可达——其中最关键的一条路径,就是它是否仍被某个存活对象的成员变量所持有。
成员变量生命周期:绑定对象,不独立存在
成员变量(即非 static 的实例字段)没有独立的生命周期。它随所属对象一起诞生,也随所属对象一同消亡。
- 对象通过 new 创建时,JVM 在堆中分配内存,并同步初始化所有成员变量(默认值或显式赋值)
- 只要该对象本身仍被至少一个强引用持有(比如局部变量、静态字段、其他对象的成员变量等),它的所有成员变量就持续有效
- 一旦对象失去所有强引用,进入不可达状态,整个对象(含所有成员变量)在下次 GC 中可能被一并回收
常见“假存活”陷阱:成员变量意外延长对象寿命
成员变量若持有外部对象引用,可能让本该回收的对象继续驻留内存,尤其在缓存、监听器、回调等场景中高发。
- 典型问题:Activity 或 Fragment 中用成员变量持有一个大 Bitmap、数据库 Cursor 或网络 Response,Activity 已 finish,但成员变量仍强引用着这些资源
- 后果:Activity 实例无法被回收 → 内存泄漏;Bitmap 等大对象长期占用堆空间 → 触发频繁 GC 甚至 OOM
- 修复思路:在生命周期结束时(如 onDestroy)主动置空成员变量,或改用 WeakReference/SoftReference 持有非关键对象
GC 判定真相:不是“变量没了”,而是“对象不可达”
垃圾回收器从 GC Roots 出发做可达性分析。成员变量只是其中一条引用链的中间节点,不是判定起点。
- 即使你写 obj.member = null,也只是断开这一条引用;若该 member 所指对象还被其他变量(如静态集合、线程局部变量)引用,它依然可达
- 反过来,如果 obj 本身已不可达(比如所在 Activity 被销毁且无其他引用),那么 obj.member 即使非 null,其所指对象也会因整条链断裂而变为不可达
- 编译器和 JVM 不会因为成员变量声明了 final 就豁免回收——final 只保证引用不可再赋值,不阻止对象被回收
实战建议:让成员变量“守好边界”
合理设计成员变量的引用关系,是避免内存泄漏最直接的防线。
- 优先使用局部变量处理临时数据,避免不必要的成员变量提升作用域
- 对生命周期短于宿主对象的资源(如 Context、View、Handler),考虑用 WeakReference 包装,防止隐式强引用
- 避免在单例或静态工具类中用成员变量持有 Activity/Fragment 实例;必须持有时,务必在 onDestory 后及时清理
- 使用 Android Studio 的 Memory Profiler 或 MAT 工具,检查 “Retained Size” 和支配树(Dominators Tree),快速定位由成员变量引发的泄漏源头
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











