# zvm **Repository Path**: guyongchang/zvm ## Basic Information - **Project Name**: zvm - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-27 - **Last Updated**: 2025-10-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README Java实现简易JVM # 主要模块和样例:
1. 读取并解析class文件,如String、Thread等类(支持jdk8及以下) 部分类可能在demo运行时用到: + `zvm\bytecode\java\lang\System.class ` + `zvm\bytecode\java\io\PrintStream.class ` + `zvm\bytecode\java\lang\Thread.class` + `zvm\bytecode\com\zvm\javaclass\integer\Table1.class(注解相关)`
2. 取opcode,解释执行程序。循环运算,入栈出栈 - 执行样例: ```java public class GaussTest { public GaussTest() { } public static void main(String[] args) { int sum = 0; for(int i = 5; i <= 20; i += 10) { sum += i; } System.out.println(sum); } } ``` 输出结果: ```java file path : GaussTest 20 ```
3. 方法调用(静态方法、构造方法、实例方法(支持继承多态)) - 静态递归方法执行样例(invokestatic): ```java public class FibonacciTest { public static void main(String[] args) { long x = fibonacci(8); System.out.println(x); } private static long fibonacci(long n) { if (n <= 1) { return n; } else { return fibonacci(n - 1) + fibonacci(n - 2); } } } ``` 输出结果: ```java file path : FibonacciTest 21 ``` - 构造方法调用(invokespecial) ```java public class FibonacciTest { public static void main(String[] args) { long x = fibonacci(8); System.out.println(x); } private static long fibonacci(long n) { if (n <= 1) { return n; } else { return fibonacci(n - 1) + fibonacci(n - 2); } } } ``` 输出结果: ```java file path : FibonacciTest 21 ``` - 调用实例方法,支持继承多态(invokevirtual) ```java public class InvokeVirtualTest { public static void main(String[] args) { Vector2D v2 = new Vector2D(2.1, 2.2); Vector2D v3 = new Vector3D(3.1, 3.2, 3.3); v2.multiply(2); v3.multiply(3); System.out.println(v2.x); System.out.println(v2.y); System.out.println(v3.x); System.out.println(v3.y); System.out.println(((Vector3D)v3).z); } } ``` 输出结果: ```java file path : ch07/InvokeVirtualTest 4.2 4.4 9.3 9.600000000000001 9.899999999999999 ```
4. 数组 - 一维int数组冒泡排序: ```java public class BubbleSortTest { public static void main(String[] args) { int[] arr = { 22, 84, 77, 11, 95, 9, 78, 56, 36, 97, 65, 36, 10, 24 ,92, 48 }; //printArray(arr); bubbleSort(arr); //System.out.println(123456789); printArray(arr); } private static void bubbleSort(int[] arr) { boolean swapped = true; int j = 0; int tmp; while (swapped) { swapped = false; j++; for (int i = 0; i < arr.length - j; i++) { if (arr[i] > arr[i + 1]) { tmp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = tmp; swapped = true; } } } } private static void printArray(int[] arr) { for (int i : arr) { System.out.println(i); } } } ``` 输出结果: ```java file path : ch08/BubbleSortTest 9 10 ... ``` - 一维double数组冒泡排序 ```java public class DoubleBubbleSortTest { public static void main(String[] args) { double[] arr = { 22.2, 84.4, 77.5, 11.2, 95.3, 9.2, 78.2, 56.2, 36.1, 97.1, 65.1, 36.1, 10.3, 24.3 ,92.3, 48.3 }; //printArray(arr); bubbleSort(arr); //System.out.println(123456789); printArray(arr); } private static void bubbleSort(double[] arr) { boolean swapped = true; int j = 0; double tmp; while (swapped) { swapped = false; j++; for (int i = 0; i < arr.length - j; i++) { if (arr[i] > arr[i + 1]) { tmp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = tmp; swapped = true; } } } } private static void printArray(double[] arr) { for (double i : arr) { System.out.println(i); } } } ``` 输出结果: ```java file path : ch08/DoubleBubbleSortTest 9.2 10.3 11.2 22.2 24.3 ... ```
5. 字符串和字符串数组 - 字符串加法,涉及类有java/lang/StringBuilder、java/lang/AbstractStringBuilder、java/lang/Math 、java/util/Arrays、java/io/FilterOutputStream、java/io/OutputStream、 java/io/PrintStream、java/lang/String: ```java public class StringBuilderTest { public static void main(String[] args) { String hello = "hello,"; String world = "world!"; String str = hello + world; System.out.println(str); } } ``` 输出结果: ```java file path : ch09/StringBuilderTest 总内存:8912 分配:8完成 当前已使用:8 总内存:8912 分配:12完成 当前已使用:20 ... hello,world! ... ``` - 字符串数组 ```java public class ArrayDemo { public static void main(String[] args) { int[] a1 = new int[10]; // newarray String[] a2 = new String[10]; // anewarray //int[][] a3 = new int[10][10]; // multianewarray int x = a1.length; // arraylength a1[0] = 100; // iastore int y = a1[0]; // iaload a2[0] = "0abc"; // aastore String s = a2[0]; // aaload System.out.println( s); a2[1] = "1xxxxyyxyy"; a2[2] = "2xxxxyyxyy"; for(int i = 0; i < 3; i++){ System.out.println(a2[i] + " stringbuilderTest"); } } } ``` 输出结果: ```java file path : ch09/ArrayDemo 总内存:8912 分配:40完成 当前已使用:40 ... 0abc 总内存:8912 分配:8完成 当前已使用:104 总内存:8912 分配:20完成 当前已使用:124 ... 0abc stringbuilderTest 总内存:8912 分配:8完成 当前已使用:364 总内存:8912 分配:32完成 当前已使用:396 ... 1xxxxyyxyy stringbuilderTest 总内存:8912 分配:8完成 当前已使用:580 总内存:8912 分配:32完成 当前已使用:612 ... 2xxxxyyxyy stringbuilderTest ... ```
6. 调用本地方法 - 只实现了这个方法println,里面调用了arraycopy ```java public class StringBuilderTest { public static void main(String[] args) { String hello = "hello,"; String world = "world!"; String str = hello + world; System.out.println(str); } } ``` 输出结果: ```java file path : ch09/StringBuilderTest hello,world! ```
7. GC相关:简单实现了标记清除算法 - 在zvm\src\main\java\com\zvm\memory\JavaHeap.java的HEAP_MAX_SIZE(此例中为32)的大小 ```java public class GCTest1 { private static final int SIZE = 3; public static void main(String[] args){ test0(); test1(); test2(); } private static void test0() { /*字符串会创建22 byte + 8byte的数组:8byte:为String对象,22byte为char[11]*/ //System.out.println("test0 start"); int[] arr = new int[SIZE]; for (int i = 0; i < SIZE; i++){ arr[i] = 100 + i; } //System.out.println("test0 start"); } private static void test1() { //System.out.println("test1 start"); int[] arr = new int[SIZE]; for (int i = 0; i < SIZE; i++){ arr[i] = 100 + i; } //System.out.println("test1 start"); } private static void test2() { //System.out.println("test2 start"); int[] arr = new int[SIZE]; for (int i = 0; i < SIZE; i++){ arr[i] = 100 + i; } //System.out.println("test2 start"); } } ``` 输出结果: ```java file path : gc/GCTest1 总内存:32 分配:12完成 当前已使用:12 总内存:32 分配:12完成 当前已使用:24 总内存:32 已使用:24 当前需分配:12 总内存:32 回收情况:24->0 当前需分配:12 总内存:32 分配:12完成 当前已使用:12 ```
### 其他 demo
1. 嵌套类 - 执行样例: ```java /** 1. 嵌套类: - 静态嵌套类; Classes - 普通内部类(成员内部类) - 局部内部类 - 匿名内部类 https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html */ public class T0NestedClass { static class StaticClass{ public String staticClassKey = "staticClassVale"; public void test(){ System.out.println(staticClassKey); } } /** * 普通内部类 */ class GenaralClass{ public String genaralClassKey = "genaralClassValue"; public void test(){ System.out.println(genaralClassKey); } } public static void main(String[] args){ class LocalClass{ public String localClassKey = "LocalClassValue"; public void test(){ System.out.println(localClassKey); } } AnonymousClass anonymousClass = new AnonymousClass(){ public String anonymousClassKey = "anonymousClassValue"; public void test(){ System.out.println(anonymousClassKey); } }; /*静态类测试*/ StaticClass staticClass = new StaticClass(); staticClass.test(); /*普通内部类测试*/ new T0NestedClass().generalClassTest(); /*局部内部类测试*/ LocalClass localClass = new LocalClass(); localClass.test(); /*匿名内部类测试*/ anonymousClass.test(); } public void generalClassTest(){ GenaralClass genaralClass = new GenaralClass(); genaralClass.test(); } } class AnonymousClass{ public void test() { } } ``` 输出结果: ```java file path : nestedclass\T0NestedClass 总内存:32000 分配:4完成 当前已使用:4 ... staticClassVale 总内存:32000 分配:0完成 当前已使用:92 总内存:32000 分配:8完成 当前已使用:100 总内存:32000 分配:8完成 当前已使用:108 总内存:32000 分配:34完成 当前已使用:142 genaralClassValue 总内存:32000 分配:4完成 当前已使用:146 总内存:32000 分配:8完成 当前已使用:154 总内存:32000 分配:30完成 当前已使用:184 LocalClassValue anonymousClassValue ```
2. 类的加载、链接、初始化 - 执行样例: ```java public class T1ClassLink { public static String value1 = "abc"; public static final String finalValue = "zvm"; public static String[] arr = new String[]{"arr0", "arr1", "dsafasfsdafd"}; public static final String[] finalArr = new String[]{"final-arr0", "final-arr1", "final-dsafasfsdafd"}; public String generalStr = "generalStr"; public T1ClassLink() { } public static void main(String[] var0) { System.out.println(value1); System.out.println("zvm"); System.out.println(arr[0]); System.out.println(finalArr[0]); System.out.println((new T1ClassLink()).generalStr); } } ``` 输出结果: ```java file path : classlink\T1ClassLink 总内存:32000 分配:0完成 当前已使用:0 ... abc 总内存:32000 分配:8完成 当前已使用:210 总内存:32000 分配:6完成 当前已使用:216 zvm 总内存:32000 分配:8完成 当前已使用:224 ... arr0 总内存:32000 分配:8完成 当前已使用:426 ... final-arr0 总内存:32000 分配:4完成 当前已使用:624 ... generalStr ```
### 计划要实现 - 反射 - 多线程 - 同步 # 怎么运行
1. 环境 - 在Windows10,基于jdk8开发 - 打印调试信息,可能需要maven引入Gson或fastjson - 支持解析jdk8及以下版本的类,解释执行demo - 经测试,demo支持在linux,jdk8中运行
2. IDEA运行
3. cmd运行 ```bash F:\projects\zvm>java -classpath E:\JAVA\Maven\com\alibaba\fastjson\1.2.62\fastjson-1.2.62.jar;E:\JAVA\Maven\com\google\code\gson\gson\2.8.5\gson-2.8.5.jar;F:\projects\zvm\target\classes com.zvm.JavaMain -cp F:\projects\zvm\bytecode gc.GCTest1 ``` 运行结果:
# 目录结构
1. 第一级目录 ``` bytecode\ #编译后的字节文件 javaclass\ #测试demo的源文件 src\ #源代码 ``` 注:由jdk1.8.0_45\jre\lib\rt.jar中的java文件夹得到zvm\bytecode\java文件夹
2. 源代码目录 ```bash com\zvm basestruct\ #读取字节码为内存中ClassFile时的基本数据结构 classfile\ #类解析相关 attribute\ #属性表:jdk8中的23种属性 constantpool\ #常量池:jdk8中10种常量类型 ClassFile.java #解析后的class文件 cp_info.java #ClassFile中的常量池表示 field_info.java #ClassFile中的字段表示 IOUtils.java #解析字节码的工具类 method_info.java #ClassFile中的方法表示 ZvmClassLoader.java #待重构 draft\ #草稿,无需理会 gc\ GC.java #GC类,目前只有标记清除算法 instruction\ #指令实现(根据Java虚拟机规范分类建立子目录) arithmetic\ #运算指令 arithmetic\ #算术运算 bitwise\ #位运算符 logic\ #逻辑运算符 relation\ #关系运算符 unary\ #一元运算符 controltransfer\ #控制转移 exception\ #抛出异常 loadandstore\ #加载和存储 constant\ #常量加载至操作数栈 load\ #局部变量表至操作数栈 store\ #操作数栈到局部变量表 methodinvocation\ #方法调用 objectcreatemanipulate\ #对象创建和操作 oprandstack\ #操作数栈操作 synchronization\ #同步 typeconversion\ #类型转换 Opcode.java #指令opcode Instruction.java #所有指令都implements这个接口 interpreter\ CallSite.java #调用方法时的入口 CodeUtils.java #控制pc的工具类 Descriptor.java #方法调用时,表示返回数据和入参结构 Interpreter.java #取opcode并执行的类 Ref.java #表示methodRef或fieldRef:含类名、描述符、方法名/字段名 jnative\ #实现本地方法 NativeConstant.java #调用相关常量 NativeMethod.java #所有本地方法都需要实现这个接口 NativeUtils.java #本地方法注册调用工具 System.java #实现System类中的本地方法 memory\ ArrayFields.java #保存堆中的数组 JavaHeap.java #表示堆,对象和数组都分配在这 MethodArea.java #方法区 ObjectFields.java #表示堆中的对象 runtime\ #运行时数据 struct\ #一些基本数据结构 JavaClass.java #运行时表示:ClassFile的入口,加一些类的信息 JavaFrame.java #运行时表示:一个方法所用的帧 JThread.java #运行时表示:一个线程(目前未实现多线程) LocalVars.java #运行时表示:帧中的局部变量表 OperandStack.java #运行时表示:帧中的操作数栈 RunTimeEnv.java #运行时的环境,包括JavaHeap、MethodMrea等 StaticVars.java #JavaClass中的静态字段分配内存 ThreadStack.java #线程栈:运行时,方法调用帧由底至上组成线程栈 Vars.java #供LocalVars、LocalVars、ObjectFields继承使用 utils\ TypeUtils.java #类型转换工具类 Cmd.java #解析命令行 JavaMain.java #启动入口类,含main方法 ZVM.java #表示虚拟机 ```
# 已实现指令(绝大部分实现了)
1. 加载(load)、存储(store)指令,将数据在局部变量表和操作数栈中来回传输 - 局部变量表->操作数栈:dload,dload_n; iload,iload_n; lload,lload_n; aload,aload_n - 操作数栈->局部变量表:dstore,dstore_n; istore,istore_n; lstore,lstore_n; astore,astore_n - 常量到操作数栈: bipush,ldc,ldc_w,ldc2_w,iconst_n
2. 运算指令 - 加法:iadd,ladd - 减法: lsub - 乘法: dmul - 自增: iinc - 比较: lcmp
3. 类型转换指令 - 待实现
4. 对象创建和操作 - 创建实例: new - 创建数组:anewarray,newarray - 访问类或实例字段:getstatic,getfield,putfield - 将一个数组元素加载到操作数栈:iaload,laload,faload,daload,aaload - 将一个操作数栈的值存储到数组中:iastore, lastore, fastore, dastore, aastore - 获得数组的长度:arraylength - 检查类实例类型的指令:instanceof、checkcast待实现
5. 操作数栈管理 - pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2, swap
6. 控制转移 - 条件分支:ifeq, ifne, iflt, ifle, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmple, if_icmpgt if_icmpge, if_acmpeq, if_acmpne - 复合条件分支:tableswitch, lookupswitch待实现 - 无条件分支: goto, goto_w, jsr, jsr_w, ret.
7. 方法调用和返回 - invokevirtual: 调用对象实例方法,根据对象实际类型分派 - invokespecial:特殊处理的实例方法:实例初始化方法,父类方法 - invokestatic:调用类方法 - invokeinterface:待实现 - 返回指令: ireturn(used to return values of type boolean , byte , char , short , or int ), lreturn, freturn, dreturn, and areturn
8. 抛出异常 - 待实现
9. 同步 - 待实现
# [wiki](https://github.com/tzh476/zvm/wiki) # 引用和参考
1. 文档、书籍参考 - [Java 虚拟机规范](https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf) - 《自己动手写 Java 虚拟机》 - Java虚拟机规范(Java se7)中文版 - Java虚拟机规范(Java se8)中文版 - 周志明的《深入理解 Java 虚拟机》
2. 代码参考 - [Go 实现 JVM](https://github.com/zxh0/jvmgo-book) - [c++ 实现的 Java 虚拟机](https://github.com/kelthuzadx/yvm) - [Hotspot 源码](https://github.com/tzh476/Hotspot) - [Java 实现 JVM](https://github.com/guxingke/mini-jvm)
3. 工具 - [类解析工具](https://github.com/zxh0/classpy)