新生代和老生代是V8根据对象存活行为动态管理的内存策略:新生代专收短命小对象,用Scavenge复制算法快速回收;老生代容纳长寿对象,采用Mark-Sweep清除与Mark-Compact整理应对碎片;对象通过晋升机制在两代间流动,全程由V8自主调度。

新生代和老生代不是预先划分好的固定区域,而是 V8 引擎根据对象存活行为动态管理的内存策略。核心在于“对象寿命”——短命小对象进新生代,长寿或大对象直奔老生代,回收方式、空间大小、触发逻辑都因此不同。
新生代:专收临时小对象,靠复制快速清理
新生代空间小(64 位 Node.js 通常 16–32 MB),严格分为两个等大的半区(From-Space 和 To-Space),只有一块用于分配新对象:
- 函数内创建的轻量对象(如
const obj = {x: 1}、短数组、临时字符串)默认进入当前活跃半区 - 超过一定大小(例如 2MB 的 ArrayBuffer)或明显长生命周期的对象,直接跳过新生代,分配到老生代
- 当活跃半区填满,触发 Scavenge 回收:扫描存活对象,复制到另一半区;复制时若对象已活过一次 GC 或 To-Space 剩余不足 25%,就晋升到老生代
- 复制完成后清空原半区,再交换 From/To 角色——整个过程通常在毫秒级完成
老生代:容纳长期驻留对象,用标记+清除+整理应对碎片
老生代是内存主力区域(默认上限约 1.4 GB,可用 --max-old-space-size 调整),存放模块缓存、全局变量、持久化 Buffer、长期闭包捕获的数据等:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不采用复制算法(成本太高),主要用 Mark-Sweep(标记-清除):先标记所有可达对象,再统一清除未标记部分
- 清除后易产生内存碎片,当碎片过多影响分配时,V8 自动触发 Mark-Compact(标记-整理),把存活对象往堆起始处挪,腾出连续大块空间
- GC 触发更保守:依赖内存使用率阈值(如达 70%)、内存压力信号,且支持增量标记(主线程穿插执行)和并发标记(后台线程处理),大幅缩短单次停顿时间
对象不是“天生属于某一代”,而是在运行中动态晋升
一个对象没有静态世代标签,它的归属由 V8 实时判定:
立即学习“Java免费学习笔记(深入)”;
- 在新生代经历两次 Scavenge 后仍存活 → 晋升至老生代
- 某次 Scavenge 中 To-Space 空间紧张(比如已用超 25%)→ 提前将部分存活对象晋升,避免分配失败
- 老生代对象新增对新生代对象的引用(写屏障检测到)→ 该新生代对象会被重点跟踪,影响后续是否晋升的决策
Vite 或前端代码本身不控制 GC,它只是运行在 V8 环境里的普通 JavaScript
Vite 是构建工具,Node.js 是运行时宿主,真正执行内存管理的是底层 V8 引擎。你写的代码、引入的库、甚至框架内部的响应式系统(如基于 WeakMap 的依赖收集),都只是向 V8 提交对象并参与可达性图——GC 的时机、范围、算法,完全由 V8 根据堆状态自主调度。

















