第 3 章 · 语言运行时与执行引擎

“学 JVM 不是为了写 Java,是为了理解’运行时’这件事本身。“


本章覆盖的课程

编号课程本章的处理方式
030深入拆解 Java 虚拟机对照系:GC 算法、内存模型、类加载 → 对标 Go runtime
080图解 Google V8执行引擎样本:隐藏类、内联缓存、JIT → 对标 Go 的编译优化
058JavaScript 核心原理解析语言设计样本:原型、闭包、异步 → 对标 Go 的接口与并发
010重学前端体系化样本:前端知识地图的构建方法
142浏览器工作原理与实践系统样本:渲染流水线、事件循环 → 对标 Go 的 GMP

为什么 Go 程序员要学这些

这 5 门课在教什么

不是教 Java 语法,也不是教前端。它们教的是四个通用的系统设计问题:

①  内存怎么自动回收?          → JVM 的 GC / V8 的 GC / Go 的 GC
②  代码怎么执行?              → JVM 的解释器+JIT / V8 的 JIT / Go 的 AOT
③  动态性怎么实现?            → JVM 的类加载 / V8 的隐藏类 / Go 的 interface
④  并发怎么组织?              → JVM 的线程 / V8 的事件循环 / Go 的 GMP

这四个问题,任何一个”带 runtime 的语言”都要回答。Go 只是给出了它自己的答案。

对照学习的价值

你只知道一种做法时,你不知道它是好是坏。 你知道三种做法,并且知道它们各自的取舍,你才算懂了。

问题JVM 的答案V8 的答案Go 的答案
内存回收分代 + 多种 GC 可选分代 + 增量标记不分代 + 并发三色标记
代码执行字节码 + 解释 + JIT字节码 + 解释 + 多层 JIT直接编译成机器码
动态分发虚方法表 (vtable)隐藏类 + 内联缓存itab(接口表)
并发1:1 线程单线程事件循环M:N goroutine
启动速度慢(JVM 启动 + 类加载)快(但要 JIT 预热)最快(直接是机器码)
峰值性能最高(JIT 能优化)高中(AOT 无运行时信息)

看完这张表,你就明白了:Go 的每一个选择都是”用峰值性能换启动速度和确定性”。


章节结构

文档内容动手项目
00-设计推演:从零造一个 GC.md★ 必读开篇:引用计数 → 标记清除 → 标记整理 → 复制式 → 分代 → 并发三色 → 写屏障 → 混合屏障,八次失败演进—
01-运行时解剖:JVM·V8·Go 三方对照.md内存布局、对象模型、执行方式、并发模型—
02-动手:用 Go 写一个 GC.md标记清除、三色标记、写屏障、并发 GC完整可运行的 GC
03-动手:字节码虚拟机与执行引擎.md栈式 VM、寄存器 VM、JIT 原理、逃逸分析字节码 VM + 逃逸分析器

★ 先读 00-设计推演。 它回答上面那个”贯穿全章的问题”的方式不是给结论, 而是让你自己走一遍:引用计数为什么栽在循环引用上、标记清除为什么停顿长、 漏标到底需要”哪两个条件同时满足”、以及”栈上加不了屏障”这个约束是怎么把 Go 逼到”必须混合屏障”这条唯一路上的。


学完这一章,你应该能

  1. 画出 JVM、V8、Go 三者堆内存布局的对比图,解释每种布局的设计动机
  2. 用 Go 实现一个可用的 GC(标记清除 + 三色标记 + 混合写屏障)
  3. 解释为什么 Go 的 GC 不需要分代,以及这个选择的代价
  4. 用 Go 实现一个字节码虚拟机,能执行一个简单的脚本语言
  5. 解释隐藏类(Hidden Class)和内联缓存(Inline Cache)的原理,并说明 Go 用什么方式解决同样的问题
  6. 解释浏览器的事件循环和 Go 的 GMP 调度器,为什么是”两种并发哲学”
  7. 回答这个问题:如果 Go 的 GC 停顿还是太长,给我六个月,我怎么改?

一个贯穿全章的问题

为什么 Go 的 GC 不做分代?

这是理解 Go runtime 设计哲学的钥匙。

标准答案(Java 视角):

分代假说(Weak Generational Hypothesis):大多数对象朝生夕死。所以把堆分成新生代和老年代,新生代用复制算法(只复制存活的少数),老年代用标记清除。

Go 的答案:

Go 没有分代,因为 Go 大量使用栈分配和值类型,堆上的对象大部分是长期存活的,分代假说在 Go 里不成立。

但这个答案引出了更多问题:

  • Go 为什么能大量用栈分配?(逃逸分析)
  • Go 的写屏障为什么必须是”混合”的?(因为不分代,没有 Remembered Set)
  • Go 的 GC 目标为什么是 1ms 而不是吞吐率?(因为 Go 主要用于在线服务)

这一章就是要让你能回答这些”为什么”。


开始阅读:00-设计推演:从零造一个 GC