{
  "schemaVersion": "0.11.0",
  "canonical": "https://www.pystone.net/notes/what-is-runtime/",
  "atlas": "https://www.pystone.net/?node=what-is-runtime#knowledge-atlas",
  "markdown": "https://www.pystone.net/notes/what-is-runtime.md",
  "context": "https://www.pystone.net/notes/what-is-runtime.context.json",
  "knowledgeVersion": "224c990773de.5fa8af6e39fa",
  "build": {
    "siteCommit": "224c990773de166d23a886306577dd90379529ce",
    "notesCommit": "5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a",
    "builtAt": "1970-01-01T00:00:00.000Z",
    "version": "224c990773de.5fa8af6e39fa"
  },
  "id": "note:what-is-runtime",
  "slug": "what-is-runtime",
  "title": "底层深入-什么是 运行时",
  "type": "note",
  "visibility": "public",
  "idStability": "rename-stable",
  "author": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "publisher": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "aliases": [],
  "summary": "底层深入 什么是 运行时",
  "contentRole": "unspecified",
  "isMoc": false,
  "mocRecognition": "none",
  "generated": false,
  "attribution": "unspecified",
  "domain": "10-计算机、信息技术与工程",
  "tags": [],
  "mocs": [],
  "contentHash": "6a673c31ea74028c4276972ebce552fc4ad645671bea8892bd37989524b055fb",
  "assets": [],
  "headings": [
    {
      "depth": 1,
      "text": "底层深入-什么是 运行时",
      "anchor": "底层深入-什么是-运行时",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E5%BA%95%E5%B1%82%E6%B7%B1%E5%85%A5-%E4%BB%80%E4%B9%88%E6%98%AF-%E8%BF%90%E8%A1%8C%E6%97%B6"
    },
    {
      "depth": 2,
      "text": "什么叫“运行时”？",
      "anchor": "什么叫运行时",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E4%BB%80%E4%B9%88%E5%8F%AB%E8%BF%90%E8%A1%8C%E6%97%B6"
    },
    {
      "depth": 2,
      "text": "几种运行时",
      "anchor": "几种运行时",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E5%87%A0%E7%A7%8D%E8%BF%90%E8%A1%8C%E6%97%B6"
    },
    {
      "depth": 3,
      "text": "Java 运行时：JVM",
      "anchor": "java-运行时jvm",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#java-%E8%BF%90%E8%A1%8C%E6%97%B6jvm"
    },
    {
      "depth": 4,
      "text": "核心抽象",
      "anchor": "核心抽象",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E6%A0%B8%E5%BF%83%E6%8A%BD%E8%B1%A1"
    },
    {
      "depth": 4,
      "text": "伪代码：类加载 + 解释循环",
      "anchor": "伪代码类加载-解释循环",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E4%BC%AA%E4%BB%A3%E7%A0%81%E7%B1%BB%E5%8A%A0%E8%BD%BD-%E8%A7%A3%E9%87%8A%E5%BE%AA%E7%8E%AF"
    },
    {
      "depth": 3,
      "text": "Mono 运行时（.NET CLR 的开源实现）",
      "anchor": "mono-运行时net-clr-的开源实现",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#mono-%E8%BF%90%E8%A1%8C%E6%97%B6net-clr-%E7%9A%84%E5%BC%80%E6%BA%90%E5%AE%9E%E7%8E%B0"
    },
    {
      "depth": 3,
      "text": "Python 运行时（CPython）",
      "anchor": "python-运行时cpython",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#python-%E8%BF%90%E8%A1%8C%E6%97%B6cpython"
    },
    {
      "depth": 3,
      "text": "ECMAScript 运行时 + Host",
      "anchor": "ecmascript-运行时-host",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#ecmascript-%E8%BF%90%E8%A1%8C%E6%97%B6-host"
    },
    {
      "depth": 4,
      "text": "语言引擎",
      "anchor": "语言引擎",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E8%AF%AD%E8%A8%80%E5%BC%95%E6%93%8E"
    },
    {
      "depth": 4,
      "text": "Host（浏览器 / Node / WeChat Game Runtime）",
      "anchor": "host浏览器-node-wechat-game-runtime",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#host%E6%B5%8F%E8%A7%88%E5%99%A8-node-wechat-game-runtime"
    },
    {
      "depth": 4,
      "text": "运行时实现",
      "anchor": "运行时实现",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%AE%9E%E7%8E%B0"
    },
    {
      "depth": 2,
      "text": "把四种运行时放在一张脑图里",
      "anchor": "把四种运行时放在一张脑图里",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E6%8A%8A%E5%9B%9B%E7%A7%8D%E8%BF%90%E8%A1%8C%E6%97%B6%E6%94%BE%E5%9C%A8%E4%B8%80%E5%BC%A0%E8%84%91%E5%9B%BE%E9%87%8C"
    },
    {
      "depth": 2,
      "text": "拓展延申：原生互操作的实现",
      "anchor": "拓展延申原生互操作的实现",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#%E6%8B%93%E5%B1%95%E5%BB%B6%E7%94%B3%E5%8E%9F%E7%94%9F%E4%BA%92%E6%93%8D%E4%BD%9C%E7%9A%84%E5%AE%9E%E7%8E%B0"
    },
    {
      "depth": 3,
      "text": "0. 设计总览",
      "anchor": "0-设计总览",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#0-%E8%AE%BE%E8%AE%A1%E6%80%BB%E8%A7%88"
    },
    {
      "depth": 3,
      "text": "1. 元数据加载阶段",
      "anchor": "1-元数据加载阶段",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#1-%E5%85%83%E6%95%B0%E6%8D%AE%E5%8A%A0%E8%BD%BD%E9%98%B6%E6%AE%B5"
    },
    {
      "depth": 3,
      "text": "2. 符号解析 & 动态库管理",
      "anchor": "2-符号解析-动态库管理",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#2-%E7%AC%A6%E5%8F%B7%E8%A7%A3%E6%9E%90-%E5%8A%A8%E6%80%81%E5%BA%93%E7%AE%A1%E7%90%86"
    },
    {
      "depth": 3,
      "text": "3. 桩（Stub）生成器",
      "anchor": "3-桩stub生成器",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#3-%E6%A1%A9stub%E7%94%9F%E6%88%90%E5%99%A8"
    },
    {
      "depth": 4,
      "text": "3.1 生成策略",
      "anchor": "31-生成策略",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#31-%E7%94%9F%E6%88%90%E7%AD%96%E7%95%A5"
    },
    {
      "depth": 4,
      "text": "3.2 桩内容模板（伪代码）",
      "anchor": "32-桩内容模板伪代码",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#32-%E6%A1%A9%E5%86%85%E5%AE%B9%E6%A8%A1%E6%9D%BF%E4%BC%AA%E4%BB%A3%E7%A0%81"
    },
    {
      "depth": 3,
      "text": "4. 封送 (Marshalling) 引擎",
      "anchor": "4-封送-marshalling-引擎",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#4-%E5%B0%81%E9%80%81-marshalling-%E5%BC%95%E6%93%8E"
    },
    {
      "depth": 3,
      "text": "5. 线程 & GC 协作",
      "anchor": "5-线程-gc-协作",
      "citation": "https://www.pystone.net/notes/what-is-runtime/#5-%E7%BA%BF%E7%A8%8B-gc-%E5%8D%8F%E4%BD%9C"
    }
  ],
  "claims": [],
  "outgoing": [],
  "incoming": [
    {
      "id": "note:game-graphics-and-runtime",
      "title": "游戏图形与运行时",
      "url": "https://www.pystone.net/notes/game-graphics-and-runtime/",
      "atlas": "https://www.pystone.net/?node=game-graphics-and-runtime#knowledge-atlas",
      "label": "游戏图形与运行时",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "WebGL中的“底层深入-什么是 运行时”导航项",
      "citation": "https://www.pystone.net/notes/game-graphics-and-runtime/#webgl"
    }
  ],
  "contentMarkdown": "# 底层深入-什么是 运行时\n\n﻿# 底层深入-什么是 运行时\n\n\n\n## 什么叫“运行时”？\n\n1. **语言规范负责说“语义”**——`for` 如何展开、异常如何传播等。\n2. **编译器/字节码生成器负责把源代码翻译成中间形式**（JVM 字节码、CIL、Python bytecode、JS bytecode…）。\n3. **运行时** = **进程内那段常驻代码 + 数据区**，在程序 *执行期* 解析/执行这些中间形式，并向宿主操作系统或宿主环境（Host）做系统调用。\n\n   * 关键职责：\n\n     * **装载**（Class Loader / Metadata Loader / `PyImport` / Script Loader）\n     * **执行引擎**（解释器循环或 JIT/AOT 生成机器码）\n     * **内存管理**（堆、栈、垃圾回收或引用计数）\n     * **运行时库**（字符串、集合、反射、I/O）\n     * **原生互操作**（JNI、P/Invoke、C-API、Web IDL…）\n\n---\n## 几种运行时\n### Java 运行时：JVM\n\n#### 核心抽象\n\n* **ClassLoader 子系统**：按委托模型链式查找 `.class` → 填充方法区元数据。([GeeksforGeeks][1])\n* **Runtime Data Area**：线程私有 *栈*、程序计数器；共享 *堆*、方法区、运行时常量池。([FreeCodeCamp][2])\n* **Execution Engine**：包含解释器与 C2/C1 JIT；遇到热点方法即从字节码生成机器码。\n* **GC**：G1/ZGC/Serial GC 等通过写屏障维护分代堆。\n\n#### 伪代码：类加载 + 解释循环\n\n```java\nbyte[] bytes = readClassFile(name);\nClass c = defineClass(bytes);        // → 方法区注册\n\nwhile (pc < bytecode.length) {       // 解释器\n    switch(bytecode[pc++]) {\n        case IADD: stack.push(stack.pop() + stack.pop()); break;\n        case INVOKEVIRTUAL:\n            Method m = cp.resolveMethod(index);\n            frameStack.push(new Frame(m));\n            break;\n        ...\n    }\n}\n```\n\n---\n\n### Mono 运行时（.NET CLR 的开源实现）\n\n* **Metadata Loader** 读取 ECMA-335 元数据表；同 JVM 的常量池。\n* **JIT/Interpreter/AOT** 三种模式可切换（iOS 可静态 AOT）。([DeepWiki][3], [Mono Project][4])\n* **GC**：SGen（分代、并行压缩）或 `libgc`；托管对象由 write barrier 追踪引用。\n* **P/Invoke**：自动生成“托管→本地”桩代码让 C# 调 C 库。\n\n伪代码（极简 JIT）\n\n```c\nIR *ir = mono_method_to_ir(method);\nCode *code = mono_codegen(ir);   // x64/arm64 等后端\nvoid* entry = jit_alloc(code->size);\nmemcpy(entry, code->bytes, code->size);\nmethod->entry = entry;\n```\n\n---\n\n### Python 运行时（CPython）\n\n* **PyInterpreterState / PyThreadState** 结构体保存全局与线程局部变量。([DeepWiki][5])\n* **字节码虚拟机**：名为 *ceval loop*，对每条 `op` 做栈式运算。\n* **内存模型**：PyObject 头部引用计数字段，循环引用靠分代 GC 回收。\n\n伪代码：核心执行循环\n\n```c\nfor (;;) {\n    int opcode = NEXTOP();\n    switch(opcode) {\n        case LOAD_FAST:  PUSH(fastlocals[i]);           break;\n        case CALL_FUNCTION:\n            PyObject *func = POP();\n            PyObject *args = POP();\n            PUSH(PyObject_Call(func, args, NULL));      break;\n        ...\n    }\n}\n```\n\n---\n\n### ECMAScript 运行时 + Host\n**ECMAScript（简称 ES）是一部由 _Ecma International_ 制定的脚本语言规范，文件编号 ECMA-262**。它定义了语言的语法、类型系统、内建对象、错误模型、并发抽象（Promise Jobs）等核心语义，用来保证不同实现之间可以运行同一段脚本代码。\n\n> - **1995 年** Brendan Eich 在 Netscape 浏览器中实现了早期的 _LiveScript/JavaScript_。\n> - 为了避免与 Sun 的“Java”商标纠纷，1996 年 Netscape 把这门语言送交标准机构 _ECMA_，双方同意用 **“ECMAScript” 作为标准名称**，浏览器实现继续对外叫 “JavaScript”。\n\n#### 语言引擎\n\n* 解析 → 生成 AST/IR → 点燃 JIT（Ignition/TurboFan、LLInt/DFG JIT…）。\n* 垃圾回收：Oilpan（V8）、Mark-Sweep/Mark-Compact。\n\n#### Host（浏览器 / Node / WeChat Game Runtime）\n\n* 提供 **事件循环队列**、DOM、`setTimeout`、`wx.request` …。\n* 规范把这些称作 **Host APIs**；语言层只认 `Job Queue` 与 `Host*` 钩子。([ECMAScript 2024 Language Specification][6], [Byby][7])\n\n伪代码：`HostPromiseRejectionTracker`\n\n```js\nfunction HostPromiseRejectionTracker(p, op) {\n  if (op === 'reject') {\n    queueMacroTask(() => {\n      if (!p.handled) dispatch('unhandledrejection', {reason: p.result});\n    });\n  } else if (op === 'handle') {\n    p.handled = true;\n  }\n}\n```\n\n微信小游戏 Runtime 在 C++ / Java 层实现 `queueMacroTask`，把任务压到主线程尾，再经 JSCore/V8 调度（与浏览器概念相同，只是没有 DOM）。\n\n#### 运行时实现\n**V8** 由 Google 于 2008 年为 Chrome 开发，名字源于 **“V-8” 引擎**，寓意高性能。\n- 它同时实现 **ECMAScript** 和 **WebAssembly**，被 Node.js、Deno、Electron、微信小游戏（Android）等运行时复用，成为最广泛部署的 ES 引擎之一。\n\n**主流 JavaScript 引擎与来源**：\n\n| 引擎                 | 主要维护方           | 首次发布 | 名称由来 / 定位                                       |\n| ------------------ | --------------- | ---- | ----------------------------------------------- |\n| **V8**             | Google          | 2008 | 命名取自 *V-8 汽车发动机*，强调“高性能”                        |\n| **SpiderMonkey**   | Mozilla         | 1996 | Brendan Eich 首个 JS 实现，被火狐延续至今                   |\n| **JavaScriptCore** | Apple / WebKit  | 2002 | Safari 内置；别名 Nitro／SquirrelFish；同样实现 ECMAScript |\n| **Hermes**         | Meta            | 2019 | React Native 专用，面向移动端低内存场景                      |\n| **QuickJS**        | Fabrice Bellard | 2019 | 超小型、支持最新 ES 特性，常嵌入 IoT                          |\n\n## 把四种运行时放在一张脑图里\n\n* **装载器**：ClassLoader / .NET MetadataLoader / `PyImport` / ScriptLoader\n* **执行引擎**：解释器 & JIT (+AOT)\n* **内存管理**：GC（分代、压缩、并行）、引用计数\n* **宿主接口**：JNI / P-Invoke / C-API / `window.*` `wx.*`\n\n> **运行时就是“让字节码真正跑起来”的那整套代码与数据区**；\n> 编写它意味着：写 Parser/JIT/GC、做平台抽象层、暴露宿主 API，并持续调优内存与性能。理解了这些通用部件，再看任何语言的“runtime”文档就能迅速对号入座。\n\n[1]: https://www.geeksforgeeks.org/jvm-works-jvm-architecture/?utm_source=chatgpt.com \"How JVM Works - JVM Architecture - GeeksforGeeks\"\n[2]: https://www.freecodecamp.org/news/jvm-tutorial-java-virtual-machine-architecture-explained-for-beginners/?utm_source=chatgpt.com \"JVM Tutorial - Java Virtual Machine Architecture Explained for Beginners\"\n[3]: https://deepwiki.com/dotnet/runtime/7-mono-runtime?utm_source=chatgpt.com \"Mono Runtime | dotnet/runtime | DeepWiki\"\n[4]: https://www.mono-project.com/docs/advanced/runtime/?utm_source=chatgpt.com \"The Mono Runtime\"\n[5]: https://deepwiki.com/python/cpython/4-runtime-and-thread-management?utm_source=chatgpt.com \"Runtime and Thread Management | python/cpython | DeepWiki\"\n[6]: https://262.ecma-international.org/?utm_source=chatgpt.com \"ECMAScript® 2024 Language Specification\"\n[7]: https://byby.dev/js-host-environments?utm_source=chatgpt.com \"JavaScript Host Environments - byby.dev\"\n\n\n## 拓展延申：原生互操作的实现\n * **原生互操作**（JNI、P/Invoke、C-API、Web IDL…）\n\n以JNI和P/Invoke为例进行说明：\n\n| 步骤         | JNI                                                                                          | P/Invoke                                                                                                 |\n| ---------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| ① 托管端声明    | `native` 关键字写进 .class → ClassFile 标志 `ACC_NATIVE`                                            | `extern` + `[DllImport]` 写进 IL → 方法标志 `pinvokeimpl`                                                      |\n| ② 运行时解析    | `System.loadLibrary()` 触发 **动态装载**；JVM 用 `dlsym/GetProcAddress` 找 `Java_pkg_Class_meth` 或注册表 | CLR 在 **JIT** 时查看元数据→调用 `LoadLibrary/dlopen` & `GetProcAddress`                                          |\n| ③ 桩代码生成    | JVM 按平台 ABI 生成 _native stub_：• 入栈 `JNIEnv*` + `jobject` + 参数• 建立 **JNI本地帧** 屏蔽 GC            | CLR 生成 **IL Stub**（.NET 7 起可用 **Source Generator**，提前产出 C#→CIL）：• 参数封送（marshal）• 线程进入 _Preemptive GC_ 模式 |\n| ④ 跨界调用     | C 函数里通过 `JNIEnv*` 表调用 JVM 服务；返回时释放本地引用                                                       | C 函数直接按 C 调用约定返回；IL Stub 再把结果封送回托管对象                                                                     |\n| ⑤ 异常/GC 协作 | C 抛异常 ⇒ `(*env)->ThrowNew` 映射到 Java；GC 不会移动 JNI 本地引用                                         | C 侧报错通过 `SetLastError`，托管层 `[DllImport(SetLastError=true)]` 捕获；GC 期间 stub 自动 pin/unpin                   |\n\n### 0. 设计总览\n\n```text\n┌─────────┐      ┌───────────────┐      ┌─────────────┐\n│  元数据 │──┐──▶│  延迟解析桩   │──┐──▶│   真正桩    │──▶ 原生函数\n└─────────┘  │   └───────────────┘  │   └─────────────┘\n             │                      │\n             ▼                      ▼\n  类加载阶段处理 ACC_NATIVE   首次调用时 patch entry\n```\n\n> **核心链路：** *标记 native → 延迟解析 → 找符号 → 生成/缓存桩 → 线程 & GC 保护 → 参数封送 → 调原生*\n\n---\n\n### 1. 元数据加载阶段\n\n| 任务               | JNI (HotSpot)             | P Invoke (CoreCLR)                   | 交付物                                   |\n| ---------------- | ------------------------- | ------------------------------------ | ------------------------------------- |\n| 解析“这是 native 方法” | `ACC_NATIVE` 写进 `Method*` | `pinvokeimpl` 写进 `MethodDesc`        | 修改 **Class/Type Loader**，支持 native 标志 |\n| 保存额外属性           | 无（符号名通过约定推算）              | `DllImport` 属性：库名、调用约定、SetLastError… | 在 **运行时元数据表** 中新增字段                   |\n\n---\n\n### 2. 符号解析 & 动态库管理\n\n| 步骤         | JNI                                                      | P Invoke                       | 要点                              |\n| ---------- | -------------------------------------------------------- | ------------------------------ | ------------------------------- |\n| 触发时机       | `System.loadLibrary()` 或第一次调用                            | JIT 初次触发 P Invoke              | 都选 **懒加载**；失败时抛高层异常             |\n| 动态装载       | `dlopen`/`LoadLibrary`                                   | 同上                             | 维护 **NativeLibraryCache**，库句柄唯一 |\n| 符号名规则      | `Java_{pkg}_{Class}_{method}__{sig}` 替换 `/ → _`,`_ → _1` | 函数名直接写在 `DllImport`            | 提供 **NameManglingUtil**（可配置）    |\n| Patch 回调地址 | `Method*::set_native_function`                           | `MethodDesc::SetNDirectTarget` | 确保线程安全，双检 + 锁或 CAS              |\n\n---\n\n### 3. 桩（Stub）生成器\n\n#### 3.1 生成策略\n\n| 维度   | JNI                                 | P Invoke                     | 建议                                          |\n| ---- | ----------------------------------- | ---------------------------- | ------------------------------------------- |\n| 生成时机 | 每个 native 方法一次（或 AOT 缓存）            | JIT 一次，或 .NET 7 起 Source Gen | 先做 **即时生成**，后期再做 AOT                        |\n| 目标   | 按平台 ABI & GC 协议包装                   | 生成 IL，再由 JIT 编译              | 统一走 **StubEmitter**：C++ 模板 + MacroAssembler |\n| 性能阶梯 | 普通 JNI → Fast JNI → Critical Native | 普通 P Invoke → Stub 内联 → 直接调用 | 暴露“Fast 调用”注解供高级用户                          |\n\n#### 3.2 桩内容模板（伪代码）\n\n```assembly\n; prologue\npush rbp\nmov  rbp, rsp\nsub  rsp, local_size\ncall ThreadState_EnterNative   ; 切换到 native / Preemptive GC\n\n; 参数封送\nmov rdx, [rbp+arg0]            ; e.g. jint → int32\n; ...\n\n; 调用原生符号\ncall [resolved_addr]\n\n; 返回值封送 / 异常映射\ncall ThreadState_LeaveNative\nmov  rsp, rbp\npop  rbp\nret\n```\n\n---\n\n### 4. 封送 (Marshalling) 引擎\n\n| 类型类别 | JNI API                              | P Invoke Attribute / API                           | 关键代码                 |\n| ---- | ------------------------------------ | -------------------------------------------------- | -------------------- |\n| 基元   | 直接复制                                 | 直接复制                                               | 无                    |\n| 字符串  | `GetStringUTFChars` / `NewStringUTF` | `[MarshalAs(UnmanagedType.LPUTF8Str)]`             | **StringMarshaller** |\n| 数组   | `GetArrayElements`        | `fixed` / `GCHandle` pin                           | **PinnedArrayPool**  |\n| 结构体  | 手写 `GetFieldID` + byte copy          | `StructLayout(LayoutKind.Sequential)`              | 解析 C# 布局元数据生成拷贝表     |\n| 异常   | `ThrowNew`, `ExceptionCheck`         | `SetLastError=true`, `Marshal.GetLastWin32Error()` | **ErrorMapper**      |\n\n---\n\n### 5. 线程 & GC 协作\n\n| 事项     | JNI                              | P Invoke                     | 实现要求                               |\n| ------ | -------------------------------- | ---------------------------- | ---------------------------------- |\n| 线程附加   | `AttachCurrentThread` / `Detach` | 自动                           | 维护 **ThreadLocal JNIEnv / GCMode** |\n| GC 安全点 | Pin 本地引用；本地帧                     | Preemptive vs Cooperative    | 在桩的 prologue / epilogue 标记状态       |\n| 反向调用   | `Call<type>Method`               | Delegate → 函数指针 (`GCHandle`) | 生成 **Reverse Stub**，确保再次切换 GC 模式   |\n"
}
