news 2026/5/22 7:05:27

弄懂 JVM 垃圾回收,是你告别 CRUD 的第一步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
弄懂 JVM 垃圾回收,是你告别 CRUD 的第一步

很多写了几年业务代码的兄弟,对 JVM 的垃圾回收(GC)都有一个巨大的误解:“既然 Java 帮我自动回收内存了,那我管它底层怎么扫地干嘛?我只要负责new对象不就行了?”

如果你抱着这个想法,那线上一旦出现接口偶尔超时、CPU 突然飙升 100%、或者半夜突然收到 OOM(内存溢出)报警,你绝对会像没头苍蝇一样抓狂。

今天,咱们不背那些干巴巴的八股文。我们就从**“怎么找垃圾”“怎么扫垃圾”,以及“懂了这些到底对咱们天天写代码有什么用”**这三个直击灵魂的角度,把 JVM 垃圾回收的底裤彻底扒掉!


一、 是什么:JVM 到底是怎么揪出“内存垃圾”的?

在 JVM 这个大工厂里,内存是极其宝贵的资源。如果你申请了内存但不用了,这就叫垃圾。那么保洁阿姨(GC 线程)怎么判断你是不是垃圾呢?

致命误区:引用计数法(Reference Counting)

很多人的第一直觉是:给每个对象贴个数字,有一个人引用它就 +1,没人引用了变成 0,就当垃圾收走。

  • 被打脸的现实:这种方法有个致命 Bug 叫**“循环引用”**。假设 A 引用了 B,B 又引用了 A,但外界根本没人用它俩。这俩货的计数器永远是 1,保洁阿姨看着它俩干瞪眼,这块内存就永远泄露了。JVM 早就抛弃了这种弱智玩法!

现代基石:可达性分析算法(Reachability Analysis)

现代 JVM 使用的是极其霸道的“顺藤摸瓜”策略。

JVM 在内部选定了一小撮绝对不能被回收的“超级大靠山”,统称为GC Roots(比如:正在执行的方法里的局部变量、类的静态变量等)。

  • 大白话直觉:保洁阿姨只认大靠山。她从 GC Roots 开始拉一根绳子往下捋。只要你能顺着这根绳子和 GC Roots 攀上关系(引用链可达),你就是良民,绝对安全。如果你和所有的大靠山都断了联系,哪怕你和另外几个废柴紧紧抱团(循环引用),在阿姨眼里也是一堆死掉的“孤岛”,统统拉去火化!


二、 核心机制:保洁阿姨的三大“扫地绝学”

找出了垃圾,接下来怎么清理?JVM 根据不同区域的特性,配备了三套不同的打扫方案。

1. 标记-清除(Mark-Sweep):最懒的做法
  • 怎么扫:第一遍走访,给所有垃圾贴上罚单(标记);第二遍走访,直接把贴罚单的垃圾原地炸毁(清除)。

  • 致命缺陷内存碎片!原地炸毁后,可用内存变得坑坑洼洼。下次你要new一个大数组,发现虽然总空间够,但连不起来,只能被迫再次触发 GC。

2. 复制算法(Copying):空间换时间的土豪玩法
  • 怎么扫:把房间一劈两半,平时只用左边。大扫除时,把左边活着的好东西,一股脑全搬到右边,并且紧紧挨着码放整齐。然后把左边直接引爆全清空。

  • 实战场景:专用于新生代!因为新生代 98% 的对象都是“朝生夕死”的,活下来的极少,搬运成本极低。最大优势是绝对没有内存碎片

3. 标记-整理(Mark-Compact):强迫症的福音
  • 怎么扫:发现垃圾后不急着炸,而是像玩“俄罗斯方块”一样,把所有活着的对象全部往内存的一侧推,紧紧贴在一起。最后把边界线以外的垃圾一刀切掉。

  • 实战场景:专用于老年代!老年代里全是活了很久的老油条,如果用复制算法太浪费空间。推一次虽然慢(会引发较长的系统停顿 STW),但一劳永逸。


三、 极简实战:几行代码,亲手制造一次“内存暗杀”

光说不练假把式。我们来看看如果不懂 GC Roots,是如何在不经意间把系统干崩溃的。

Java

import java.util.ArrayList; import java.util.List; public class GCRootLeakDemo { // 致命毒药:这是一个 static 变量! // 在 JVM 规范里,类的静态属性是铁打的 GC Root(大靠山)! private static final List<byte[]> MEMORY_LEAK_LIST = new ArrayList<>(); public static void main(String[] args) throws InterruptedException { System.out.println("====== 危险业务上线 ======"); while (true) { // 模拟用户请求:每次请求产生 1MB 的临时数据 byte[] tempData = new byte[1024 * 1024]; // 实习生为了所谓“统计”或“缓存”,把临时数据塞进了静态集合里 MEMORY_LEAK_LIST.add(tempData); System.out.println("处理了一次请求,向静态集合塞入 1MB 数据..."); Thread.sleep(100); // 注意:因为 tempData 被 static 的 MEMORY_LEAK_LIST 死死抓住, // 哪怕这次请求结束了,这 1MB 数据依然与 GC Root 可达! // 保洁阿姨根本不敢动它!最终必将 OOM! } } } /** * 运行输出(搭配 -Xmx50m 运行): * ====== 危险业务上线 ====== * 处理了一次请求,向静态集合塞入 1MB 数据... * ... (几十次之后) * Exception in thread "main" java.lang.OutOfMemoryError: Java heap space */

看懂了吗?这就是线上最经典的内存泄漏场景!因为你不懂静态变量是 GC Root,无限制地往里面塞东西,导致垃圾永远无法被回收,硬生生把内存撑爆了。


四、 灵魂拷问:懂了 GC,对天天写 CRUD 的你有什么意义?

如果你能把上面的逻辑盘明白,你的代码段位就已经超越了 80% 的同行。了解 GC 对开发者的真实意义,体现在以下三大“避坑”直觉中:

业务开发常见操作不懂 GC 的灾难后果懂 GC 的神仙操作(降维打击)
滥用全局缓存直接弄个static Map存用户 Token,越存越多,由于是 GC Root,老年代塞满,系统一天崩一次。明白生命周期,改用 Redis,或者使用具备淘汰机制的本地缓存(如 Guava Cache / Caffeine)。
超大对象的创建查数据库时,动不动就select *捞几十万条数据塞进 List。知道超大对象会直接绕过新生代,砸进老年代引发极耗时的 Full GC 导致接口卡死。果断改用分页查询!
ThreadLocal 的使用线程池里用完ThreadLocal不调用remove()知道 ThreadLocalMap 的 Key 是弱引用,但 Value 是强引用。线程不销毁,Value 就一直与线程(GC Root)可达,导致隐蔽的内存泄漏!用完必在finallyremove
接口偶发性超时接口平时 20ms,偶尔几秒钟不响应,到处抓包查网络。意识到可能是触发了老年代的 GC 导致了STW (Stop-The-World 全局停顿)。直接去查 GC 日志,调整年轻代比例或更换 G1 回收器来平滑停顿时间。

总结一句话

学习垃圾回收,绝不是为了去造一个 JVM。而是让你在写每一行new Object()、定义每一个static变量时,脑子里都能清晰地看到这块内存未来的生老病死。这种掌控感,才是高级工程师和代码搬运工的核心壁垒。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 7:05:08

5个简单步骤:大麦抢票开源工具如何帮你告别手速焦虑

5个简单步骤&#xff1a;大麦抢票开源工具如何帮你告别手速焦虑 【免费下载链接】ticket-purchase 大麦自动抢票&#xff0c;支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到心仪演唱会门票而烦恼吗…

作者头像 李华
网站建设 2026/4/1 17:43:31

Vitest企业级测试架构解析:Vite生态下的测试范式革新

Vitest企业级测试架构解析&#xff1a;Vite生态下的测试范式革新 【免费下载链接】vitest Next generation testing framework powered by Vite. 项目地址: https://gitcode.com/GitHub_Trending/vi/vitest Vitest作为基于Vite生态的下一代测试框架&#xff0c;正在重新…

作者头像 李华
网站建设 2026/4/1 17:42:26

西门子1200控制V90伺服的应用案例

西门子1200控制V90伺服&#xff0c;西门子1200通过PN通讯控制 V90伺服&#xff0c;程序控制采用FB285功能块&#xff0c;该项目采用中文注释&#xff0c;注释详细&#xff0c;还包括与多台G120 PN通讯控制非常适合大家学习与使用支持博图14及以上版本&#xff0c;实际应用案例&…

作者头像 李华
网站建设 2026/4/1 17:42:24

Intel RealSense深度视觉开发:16位深度图与RGB图同步采集与保存实战

1. 从零开始搭建RealSense开发环境 第一次接触Intel RealSense摄像头时&#xff0c;我被它强大的深度感知能力惊艳到了。这玩意儿不仅能像普通摄像头一样捕捉彩色图像&#xff0c;还能通过红外传感器获取每个像素点的距离信息。不过要玩转这个黑科技&#xff0c;得先把开发环境…

作者头像 李华
网站建设 2026/4/1 17:41:46

万象视界灵坛实战教程:用自定义神谕标签实现小样本冷启动视觉理解

万象视界灵坛实战教程&#xff1a;用自定义神谕标签实现小样本冷启动视觉理解 1. 什么是万象视界灵坛 万象视界灵坛是一款基于OpenAI CLIP技术的高级多模态智能感知平台。它将复杂的视觉识别任务转化为直观的交互体验&#xff0c;特别适合需要快速理解图像内容但缺乏大量标注…

作者头像 李华