Java GC学习关键在于建立“判断—回收—调优”三层直觉:先通过代码实操定位对象生死,再读懂GC日志理解回收触发与过程,接着用MAT分析内存泄漏,最后通过参数调整与压测验证调优效果。

练Java垃圾回收(GC)精华,关键不是背概念,而是建立“判断—回收—调优”三层直觉:先能快速定位对象生死,再理解不同场景下JVM怎么清理,最后能看懂日志、改参数、压测验证。下面分四块实操路径,每一块都带可动手的点。
一、从代码里亲手“杀死”一个对象
别只看理论,写几行代码验证GC行为:
- 用
new Object()创建对象后立刻置为null,配合System.gc()(仅触发建议),观察是否真被回收(可用Runtime.getRuntime().freeMemory()前后对比) - 故意构造循环引用(如A持有B、B持有A),再断掉外部引用,用VisualVM或JConsole观察堆内存变化——你会发现它没被回收,从而真正理解“为什么不用引用计数”
- 把对象放入
WeakReference,然后主动触发GC,立刻调用get(),返回null就说明弱引用已失效——这是软/弱/虚引用最直观的入门方式
二、读懂一次GC日志,胜过十遍算法描述
启动JVM时加参数:-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log,跑一段有对象频繁创建销毁的代码(比如循环创建字符串、List)。打开gc.log,重点盯三件事:
- 看时间戳和停顿时间(
pause或GC pause),区分是Young GC还是Full GC - 找“
PSYoungGen”、“ParOldGen”这类关键词,对应新生代/老年代使用量变化 - 留意“
allocation failure”——这是GC被触发的直接原因,不是“内存满了”,而是“Eden区不够分配新对象了”
三、用MAT定位一次真实内存泄漏
下载一个含内存泄漏的Demo(比如静态集合不断add对象却不remove),用JDK自带jmap生成堆转储:jmap -dump:format=b,file=heap.hprof <pid>,再用Eclipse MAT打开:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- 先看
Leak Suspects报告,MAT会自动标出可疑对象 - 点开
Dominator Tree,找占用内存Top 3的对象,看谁在“死死拽着”它们不放(比如某个静态Map的value里藏着大量未释放的业务对象) - 右键→
Path to GC Roots → with all references,就能看到从GC Roots到泄漏对象的完整引用链——这才是排查泄漏的核心动作
四、调一次参数,跑一次压测,比十次纸上谈兵管用
选一个简单Web接口(如Spring Boot的/hello),用JMeter或wrk压到每秒几百请求,观察GC频率和延迟:
- 先用默认参数跑,记下平均响应时间和GC次数
- 尝试调大新生代:
-Xmx2g -Xms2g -XX:NewRatio=1(让新生代占堆一半),再压,对比Young GC次数是否下降 - 换成G1收集器:
-XX:+UseG1GC -XX:MaxGCPauseMillis=50,看停顿是否更稳——注意不是所有场景G1都更好,小堆(
不复杂但容易忽略:GC不是越少越好,而是“在业务可接受的停顿内,用最少的GC完成最多的内存释放”。练熟这四步,面试聊GC时,你讲的就不是“标记清除”,而是“上周我用MAT发现线程局部变量没清空,导致Connection对象卡在老年代,加了try-with-resources后Full GC从每小时3次降到每天1次”。

















