Java通过GC自动回收内存,基于可达性分析判断对象存活,从GC Roots出发搜索引用链,不可达对象被回收;不同GC算法(如Serial、G1、ZGC)权衡吞吐量、延迟与内存占用。

Java里不手动free内存,靠GC自动回收
因为Java把内存分配和释放的控制权从开发者手里拿走了——new对象时JVM自动在堆上分配空间,但没有对应的free或delete语法。这避免了C/C++里常见的野指针、重复释放、忘记释放等错误,代价是必须有一套机制来识别哪些对象“已经没人用了”,然后安全地回收它们。这个机制就是垃圾收集器(GC)。
GC判断“对象是否存活”只看可达性,不是引用计数
Java GC不用引用计数法(比如Python部分场景用的),而是基于**可达性分析(Reachability Analysis)**:从一组称为GC Roots的引用出发(如栈帧里的局部变量、静态字段、JNI引用等),沿着引用链向下搜索;所有能被遍历到的对象视为“存活”,其余不可达对象就标记为可回收。
这意味着:
-
Object a = new Object(); Object b = a; a = null;—— 只要b还持有引用,对象就不会被回收 - 循环引用(A持有B,B持有A)完全不影响GC判定,只要两者都从GC Roots不可达,就会被一起回收
- 弱引用(
WeakReference)、软引用(SoftReference)会影响GC时机,但不改变“是否可达”的基本逻辑
不同GC算法影响吞吐量、延迟和内存占用
GC不是只有一个实现,而是有多种策略,对应不同应用场景:
立即学习“Java免费学习笔记(深入)”;
本文档主要讲述的是关于Objective-C手动内存管理的规则;在ios开发中Objective-C 增加了一些新的东西,包括属性和垃圾回收。那么,我们在学习Objective-C之前,最好应该先了解,从前是什么样的,为什么Objective-C 要增加这些支持。有需要的朋友可以下载看看
-
Serial GC:单线程,适合小堆、客户端程序;停顿明显,但简单轻量 -
G1 GC(默认自JDK 9起):分区域回收,可预测停顿时间;适合大堆(>4GB)、低延迟要求服务 -
ZGC/Shenandoah:目标是毫秒级停顿(
选错GC可能导致频繁Full GC、STW时间过长、或吞吐量骤降——比如用Serial跑一个8核+32GB堆的Spring Boot服务,基本等于自己给自己加锁。
开发者仍需关注内存泄漏,GC不是万能解药
GC只能回收“不可达”对象,但很多泄漏是对象**本该不可达却一直被意外持有**,比如:
- 静态集合类(
static Map)不断put却不removecache - ThreadLocal变量未调用
remove(),导致线程复用时对象长期滞留 - 监听器/回调注册后忘记反注册(尤其GUI或Android)
- 使用不当的缓存框架(如没配最大容量、过期策略)
这类问题不会报错,但堆内存持续增长,最终触发频繁GC甚至OutOfMemoryError: Java heap space。这时候得用jmap + mat或VisualVM分析堆快照,而不是指望GC“更努力一点”。
真正关键的不是GC存在与否,而是理解它不做什么:它不帮你理清业务逻辑里的生命周期,也不替你决定一个对象该活多久。那部分,还是得写代码的人来定。









