{"id":26279573,"url":"https://github.com/null-object-0000/newbie-mini-jvm","last_synced_at":"2025-03-14T14:15:29.470Z","repository":{"id":282333461,"uuid":"946633960","full_name":"null-object-0000/newbie-mini-jvm","owner":"null-object-0000","description":"此项目将试图让工作多年的 Java 程序员通过自己动手写 Java 虚拟机的方式深入理解 JVM 原理。","archived":false,"fork":false,"pushed_at":"2025-03-14T02:00:37.000Z","size":10,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-14T02:43:32.564Z","etag":null,"topics":["jvm","study"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/null-object-0000.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-11T12:50:48.000Z","updated_at":"2025-03-14T02:00:41.000Z","dependencies_parsed_at":"2025-03-14T02:43:36.315Z","dependency_job_id":"2dea700a-ff64-4ef7-aa11-2d0dd5838729","html_url":"https://github.com/null-object-0000/newbie-mini-jvm","commit_stats":null,"previous_names":["null-object-0000/newbie-mini-jvm"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-mini-jvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-mini-jvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-mini-jvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/null-object-0000%2Fnewbie-mini-jvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/null-object-0000","download_url":"https://codeload.github.com/null-object-0000/newbie-mini-jvm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243589330,"owners_count":20315471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jvm","study"],"created_at":"2025-03-14T14:15:28.853Z","updated_at":"2025-03-14T14:15:29.434Z","avatar_url":"https://github.com/null-object-0000.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# newbie-mini-jvm\n\n此项目将试图让工作多年的 Java 程序员通过自己动手写 Java 虚拟机的方式深入理解 JVM 原理。本人在开启这个项目时对于 JVM 也无深入了解，希望在不久的将来可以通过此种方式有所学习。\n\n本人将主要依照 [尚硅谷宋红康 JVM 全套教程（详解 java 虚拟机）](https://www.bilibili.com/video/BV1PJ411n7xZ) 视频为基础，并结合 [《自己动手写 Java 虚拟机》](https://github.com/zxh0/jvmgo-book) 来逐步学习与完善。下面是一些编码约定，了解过后我们就可以开始动手了：\n\n- 使用 Java 21 编写代码，JUnit 5 编写单元测试，Maven 作为构建工具\n- 所有的核心类都以 `mini` 开头，表示这是一个迷你版的 JVM\n\n## 一、前置知识准备\n\n### 1. JVM 体系结构总览\n\u003e Java 是一种跨平台的编程语言，JVM 是 Java 的运行时环境，负责执行 Java 字节码。JVM 使得 Java 程序可以在不同的平台上运行，而不需要重新编译。\n\n#### JVM 体系结构\n- 类加载器（Class Loader）：负责加载 Java 类文件，并将其转换为 JVM 可以理解的格式。\n- 运行时数据区（Runtime Data Area）：JVM 在运行时使用的内存区域，包括方法区、堆、虚拟机栈、本地方法栈和程序计数器。\n- 执行引擎（Execution Engine）：负责执行字节码指令，包括解释器和即时编译器（JIT）。\n- 本地接口（Native Interface）：用于与其他编程语言（如 C/C++）进行交互。\n- 垃圾回收器（Garbage Collector）：负责自动管理内存，回收不再使用的对象。\n\n### 2. 字节码执行引擎\n\u003e 把这一章节提前主要是因为我的个人兴趣，对能先实现这一步感到很开心（嗯，也因为这部分在这里只是先实现了指令的映射，相对简单），之后我们将会基于这个“字节码执行引擎”逐步完善我们的 JVM。\n\n我们编写了一个简单的 Java 程序，源码见：[HelloStackVM.java](./src/main/java/demo/HelloStackVM.java) （未来我们的目标就是用自己的 JVM 来执行这个 Java 程序。）\n\n然后我们通过 `javac` 和 `javap` 命令来查看编译后的字节码指令。\n\n```bash\n$ javac ./src/main/java/demo/HelloStackVM.java\n$ javap -c ./src/main/java/demo/HelloStackVM.class\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e点击展开查看详情\u003c/summary\u003e\n\n通过 `javap` 我们可以看到 `HelloStackVM` 类的字节码指令集，我们重点关注 `main` 方法的字节码指令集 ，下面以表格的形式对应字节码指令和\nJava 源码的关系：\n\n| Java 源码                | 字节码指令                                            |\n| ------------------------ | ----------------------------------------------------- |\n| `int a = 3;`             | `iconst_3` `istore_1`                                 |\n| `int b = 4;`             | `iconst_4` `istore_2`                                 |\n| `int c = a + b;`         | `iload_1` `iload_2` `iadd` `istore_3`                 |\n| `System.out.println(c);` | `getstatic` `iload_3` `invokedynamic` `invokevirtual` |\n| `return;`                | `return`                                              |\n\n我们来分析一下字节码指令（只需要了解大致意思即可）：\n\n- `iconst_3`：将整数常量 3 压入操作数栈。\n- `istore_1`：将操作数栈顶的整数值存入局部变量表的第 1 个位置。\n- `iload_1`：将局部变量表第 1 个位置的整数值压入操作数栈。\n- `iadd`：将操作数栈顶的两个整数值相加，并将结果压入操作数栈。\n- `istore_3`：将操作数栈顶的整数值存入局部变量表的第 3 个位置。\n- `getstatic`：获取静态字段的值，并将其压入操作数栈。\n- `invokedynamic`：动态调用方法。\n- `invokevirtual`：调用实例方法。\n- `return`：返回。\n\u003c/details\u003e\n\n由于 JVM 使用的指令集架构是`栈的指令集架构`（还有一种是`寄存器的指令集架构`），所以在开始之前，我们需要先来了解一种数据结构：栈。\n\n\u003cdetails\u003e\n\u003csummary\u003e点击展开查看详情\u003c/summary\u003e\n\n#### 栈（Stack）\n\n栈是一种后进先出（LIFO）的数据结构，具有以下特点：\n\n- 只能在栈顶进行插入和删除操作。\n- 栈顶元素是最后插入的元素，栈底元素是最先插入的元素。\n\n有两种常见的栈实现方式：\n\n| 实现方式 | 关键说明                               | 优点                   | 缺点           |\n| -------- | -------------------------------------- | ---------------------- | -------------- |\n| 数组     | 通过索引直接访问元素，无需遍历链表节点 | 内存连续，CPU 缓存友好 | 扩容需复制数据 |\n| 链表     | 动态分配内存，插入/删除效率高          | 无固定大小限制         | 内存碎片化     |\n\n我们使用链表来实现栈，链表的每个节点包含一个数据域和一个指向下一个节点的指针。源码见：[MiniStack.java](./src/main/java/data/structure/MiniStack.java)\n\n\u003c/details\u003e\n\n为什么要使用栈呢？因为 Java 虚拟机的字节码指令集是基于栈的，所有的操作都是在操作数栈上进行的。\n\n#### 基于栈的虚拟机\n\n接下来我们来实现一个可以执行字节码指令的虚拟机，源码见：[MiniStackVM.java](./src/main/java/mini/MiniStackVM.java)\n\n另外我们还在单元测试中模拟了 `HelloStackVM` 类的 `main`\n方法的字节码指令集，来验证我们实现的虚拟机是否正确。源码见：[MiniStackVMTest.java](./src/test/java/mini/MiniStackVMTest.java)\n\n## 二、类加载器\n\n### 1. 类文件解析\n\n本章将解析.class文件的二进制格式，包括魔数、版本号、常量池等结构的读取与校验。\n\n### 2. 类加载机制\n\n实现类加载器的双亲委派模型，支持从文件系统加载类并生成 `Class` 对象。\n- **类加载流程**：加载 -\u003e 验证 -\u003e 准备 -\u003e 解析 -\u003e 初始化。\n- **双亲委派模型**：子加载器优先委派父加载器加载类，确保核心类库安全性。\n\n## 三、执行引擎\n\n实现字节码指令的执行引擎，支持基本的算术运算、类型转换、控制流等指令。\n\n## 四、运行时数据区\n\n构建虚拟机内存模型，包含方法区、堆、虚拟机栈等核心组件。\n\n## 五、垃圾回收\n\n实现垃圾回收机制，包括标记-清除算法和分代回收策略。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnull-object-0000%2Fnewbie-mini-jvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnull-object-0000%2Fnewbie-mini-jvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnull-object-0000%2Fnewbie-mini-jvm/lists"}