用Java实现JVM第五章《指令集和解释器》
案例介绍
本案例通过java代码实现jvm规范中指令集和解释器,完成后就可以开始执行1到100的加和计算。
Java虚拟机顾名思义,就是一台虚拟的机器,而字节码(bytecode)就是运行在这台虚拟机器上的机器码。我们已经知道,每一个类或者接口都会被Java编译器编译成一个class文件,类或接口的方法信息就放在class文件的method_info结构中。如果方法不是抽象的,也不是本地方法,方法的Java代码就会被编译器编译成字节码(即使方法是空的,编译器也会生成一条return语句),存在method_info结构的Code属性中。
环境准备
1、jdk 1.8.0
2、IntelliJ IDEA Community Edition 2018.3.1 x64
配置信息
1、调试配置
2.1、配置位置:Run/Debug Configurations -> program arguments
2.2、配置内容:-Xjre “C:\Program Files\Java\jdk1.8.0_161\jre” E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\test-classes\org\itstack\demo\test\HelloWorld
代码示例
itstack-demo-jvm-05
├── pom.xml
└── src└── main│ └── java│ └── org.itstack.demo.jvm│ ├── classfile│ │ ├── attributes {BootstrapMethods/Code/ConstantValue...}│ │ ├── constantpool {CONSTANT_TAG_CLASS/CONSTANT_TAG_FIELDREF/CONSTANT_TAG_METHODREF...}│ │ ├── ClassFile.java│ │ ├── ClassReader.java│ │ └── MemberInfo.java │ ├── classpath│ │ ├── impl│ │ │ ├── CompositeEntry.java│ │ │ ├── DirEntry.java │ │ │ ├── WildcardEntry.java │ │ │ └── ZipEntry.java │ │ ├── Classpath.java│ │ └── Entry.java │ ├── classpath│ │ ├── base│ │ ├── comparisons│ │ ├── constants│ │ ├── control│ │ ├── conversions│ │ ├── extended│ │ ├── loads│ │ ├── math│ │ │ ├── add│ │ │ ├── and│ │ │ ├── div│ │ │ ├── iinc│ │ │ ├── mul│ │ │ ├── neg│ │ │ ├── or│ │ │ ├── rem│ │ │ ├── sh│ │ │ ├── sub│ │ │ └── xor│ │ ├── stack│ │ ├── store│ │ └── Factory │ ├── rtda│ │ ├── Frame.java│ │ ├── JvmStack.java│ │ ├── LocalVars.java│ │ ├── OperandStack.java│ │ ├── Slot.java │ │ └── Thread.java│ ├── Cmd.java│ ├── Interpret.java │ └── Main.java└── test└── java└── org.itstack.demo.test└── HelloWorld.java
Factory.java
public class Factory {public static Instruction newInstruction(byte opcode) {switch (opcode) {case 0x00:return new NOP();case 0x01:return new ACONST_NULL();case 0x02:return new ICONST_M1();case 0x03:return new ICONST_0();case 0x04:return new ICONST_1();case 0x05:return new ICONST_2();case 0x06:return new ICONST_3();case 0x07:return new ICONST_4();case 0x08:return new ICONST_5();case 0x09:return new LCONST_0();case 0x0a:return new LCONST_1();case 0x0b:return new FCONST_0();case 0x0c:return new FCONST_1();case 0x0d:return new FCONST_2();case 0x0e:return new DCONST_0();case 0x0f:return new DCONST_1();case 0x10:return new BIPUSH();case 0x11:return new SIPUSH();// case 0x12:// return &LDC{}// case 0x13:// return &LDC_W{}// case 0x14:// return &LDC2_W{}case 0x15:return new ILOAD();case 0x16:return new LLOAD();case 0x17:return new FLOAD();case 0x18:return new DLOAD();case 0x19:return new ALOAD();case 0x1a:return new ILOAD_0();case 0x1b:return new ILOAD_1();case 0x1c:return new ILOAD_2();case 0x1d:return new ILOAD_3();case 0x1e:return new LLOAD_0();case 0x1f:return new LLOAD_1();case 0x20:return new LLOAD_2();case 0x21:return new LLOAD_3();case 0x22:return new FLOAD_0();case 0x23:return new FLOAD_1();case 0x24:return new FLOAD_2();case 0x25:return new FLOAD_3();case 0x26:return new DLOAD_0();case 0x27:return new DLOAD_1();case 0x28:return new DLOAD_2();case 0x29:return new DLOAD_3();case 0x2a:return new ALOAD_0();case 0x2b:return new ALOAD_1();case 0x2c:return new ALOAD_2();case 0x2d:return new ALOAD_3();// case 0x2e:// return iaload// case 0x2f:// return laload// case 0x30:// return faload// case 0x31:// return daload// case 0x32:// return aaload// case 0x33:// return baload// case 0x34:// return caload// case 0x35:// return saloadcase 0x36:return new ISTORE();case 0x37:return new LSTORE();case 0x38:return new FSTORE();case 0x39:return new DSTORE();case 0x3a:return new ASTORE();case 0x3b:return new ISTORE_0();case 0x3c:return new ISTORE_1();case 0x3d:return new ISTORE_2();case 0x3e:return new ISTORE_3();case 0x3f:return new LSTORE_0();case 0x40:return new LSTORE_1();case 0x41:return new LSTORE_2();case 0x42:return new LSTORE_3();case 0x43:return new FSTORE_0();case 0x44:return new FSTORE_1();case 0x45:return new FSTORE_2();case 0x46:return new FSTORE_3();case 0x47:return new DSTORE_0();case 0x48:return new DSTORE_1();case 0x49:return new DSTORE_2();case 0x4a:return new DSTORE_3();case 0x4b:return new ASTORE_0();case 0x4c:return new ASTORE_1();case 0x4d:return new ASTORE_2();case 0x4e:return new ASTORE_3();// case 0x4f:// return iastore// case 0x50:// return lastore// case 0x51:// return fastore// case 0x52:// return dastore// case 0x53:// return aastore// case 0x54:// return bastore// case 0x55:// return castore// case 0x56:// return sastorecase 0x57:return new POP();case 0x58:return new POP2();case 0x59:return new DUP();case 0x5a:return new DUP_X1();case 0x5b:return new DUP_X2();case 0x5c:return new DUP2();case 0x5d:return new DUP2_X1();case 0x5e:return new DUP2_X2();case 0x5f:return new SWAP();case 0x60:return new IADD();case 0x61:return new LADD();case 0x62:return new FADD();case 0x63:return new DADD();case 0x64:return new ISUB();case 0x65:return new LSUB();case 0x66:return new FSUB();case 0x67:return new DSUB();case 0x68:return new IMUL();case 0x69:return new LMUL();case 0x6a:return new FMUL();case 0x6b:return new DMUL();case 0x6c:return new IDIV();case 0x6d:return new LDIV();case 0x6e:return new FDIV();case 0x6f:return new DDIV();case 0x70:return new IREM();case 0x71:return new LREM();case 0x72:return new FREM();case 0x73:return new DREM();case 0x74:return new INEG();case 0x75:return new LNEG();case 0x76:return new FNEG();case 0x77:return new DNEG();case 0x78:return new ISHL();case 0x79:return new LSHL();case 0x7a:return new ISHR();case 0x7b:return new LSHR();case 0x7c:return new IUSHR();case 0x7d:return new LUSHR();case 0x7e:return new IAND();case 0x7f:return new LAND();case (byte) 0x80:return new IOR();case (byte) 0x81:return new LOR();case (byte) 0x82:return new IXOR();case (byte) 0x83:return new LXOR();case (byte) 0x84:return new IINC();case (byte) 0x85:return new I2L();case (byte) 0x86:return new I2F();case (byte) 0x87:return new I2D();case (byte) 0x88:return new L2I();case (byte) 0x89:return new L2F();case (byte) 0x8a:return new L2D();case (byte) 0x8b:return new F2I();case (byte) 0x8c:return new F2L();case (byte) 0x8d:return new F2D();case (byte) 0x8e:return new D2I();case (byte) 0x8f:return new D2L();case (byte) 0x90:return new D2F();case (byte) 0x91:return new I2B();case (byte) 0x92:return new I2C();case (byte) 0x93:return new I2S();case (byte) 0x94:return new LCMP();case (byte) 0x95:return new FCMPL();case (byte) 0x96:return new FCMPG();case (byte) 0x97:return new DCMPL();case (byte) 0x98:return new DCMPG();case (byte) 0x99:return new IFEQ();case (byte) 0x9a:return new IFNE();case (byte) 0x9b:return new IFLT();case (byte) 0x9c:return new IFGE();case (byte) 0x9d:return new IFGT();case (byte) 0x9e:return new IFLE();case (byte) 0x9f:return new IF_ICMPEQ();case (byte) 0xa0:return new IF_ICMPNE();case (byte) 0xa1:return new IF_ICMPLT();case (byte) 0xa2:return new IF_ICMPGE();case (byte) 0xa3:return new IF_ICMPGT();case (byte) 0xa4:return new IF_ICMPLE();case (byte) 0xa5:return new IF_ACMPEQ();case (byte) 0xa6:return new IF_ACMPNE();case (byte) 0xa7:return new GOTO();// case 0xa8:// return &JSR{}// case 0xa9:// return &RET{}case (byte) 0xaa:return new TABLE_SWITCH();case (byte) 0xab:return new LOOKUP_SWITCH();// case 0xac:// return ireturn// case 0xad:// return lreturn// case 0xae:// return freturn// case 0xaf:// return dreturn// case 0xb0:// return areturn// case 0xb1:// return _return// case 0xb2:// return &GET_STATIC{}// case 0xb3:// return &PUT_STATIC{}// case 0xb4:// return &GET_FIELD{}// case 0xb5:// return &PUT_FIELD{}// case 0xb6:// return &INVOKE_VIRTUAL{}// case 0xb7:// return &INVOKE_SPECIAL{}// case 0xb8:// return &INVOKE_STATIC{}// case 0xb9:// return &INVOKE_INTERFACE{}// case 0xba:// return &INVOKE_DYNAMIC{}// case 0xbb:// return &NEW{}// case 0xbc:// return &NEW_ARRAY{}// case 0xbd:// return &ANEW_ARRAY{}// case 0xbe:// return arraylength// case 0xbf:// return athrow// case 0xc0:// return &CHECK_CAST{}// case 0xc1:// return &INSTANCE_OF{}// case 0xc2:// return monitorenter// case 0xc3:// return monitorexitcase (byte) 0xc4:return new WIDE();// case 0xc5:// return &MULTI_ANEW_ARRAY{}case (byte) 0xc6:return new IFNULL();case (byte) 0xc7:return new IFNONNULL();case (byte) 0xc8:return new GOTO_W();// case 0xc9:// return &JSR_W{}// case 0xca: breakpoint// case 0xfe: impdep1// case 0xff: impdep2default:return null;}}}
Interpret.java
//指令集解释器
class Interpret {Interpret(MemberInfo m) {CodeAttribute codeAttr = m.codeAttribute();int maxLocals = codeAttr.maxLocals();int maxStack = codeAttr.maxStack();byte[] byteCode = codeAttr.data();Thread thread = new Thread();Frame frame = thread.newFrame(maxLocals, maxStack);thread.pushFrame(frame);loop(thread, byteCode);}private void loop(Thread thread, byte[] byteCode) {Frame frame = thread.popFrame();BytecodeReader reader = new BytecodeReader();while (true) {//循环int pc = frame.nextPC();thread.setPC(pc);//decodereader.reset(byteCode, pc);byte opcode = reader.readByte();Instruction inst = Factory.newInstruction(opcode);if (null == inst) {System.out.println("寄存器(指令)尚未实现 " + byteToHexString(new byte[]{opcode}));break;}inst.fetchOperands(reader);frame.setNextPC(reader.pc());System.out.println("寄存器(指令):" + byteToHexString(new byte[]{opcode}) + " -> " + inst.getClass().getSimpleName() + " => 局部变量表:" + JSON.toJSONString(frame.operandStack().getSlots()) + " 操作数栈:" + JSON.toJSONString(frame.operandStack().getSlots())); //execinst.execute(frame);}}private static String byteToHexString(byte[] codes) {StringBuilder sb = new StringBuilder();sb.append("0x");for (byte b : codes) {int value = b & 0xFF;String strHex = Integer.toHexString(value);if (strHex.length() < 2) {strHex = "0" + strHex;}sb.append(strHex);}return sb.toString();}}
HelloWorld.java
package org.itstack.demo.test;public class HelloWorld {public static void main(String[] args) {int sum = 0;for (int i = 1; i <= 100; i++) {sum += i;}System.out.println(sum);}}
测试结果 {此时还不能输出结果,但是在操作数据栈中已经可以看到结果:5050}
"C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1\lib\idea_rt.jar=61887:D:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\classes;D:\Program Files (x86)\apache-maven-2.2.1\repository\com\beust\jcommander\1.72\jcommander-1.72.jar;D:\Program Files (x86)\apache-maven-2.2.1\repository\org\projectlombok\lombok\1.18.0\lombok-1.18.0.jar;D:\Program Files (x86)\apache-maven-2.2.1\repository\com\alibaba\fastjson\1.2.40\fastjson-1.2.40.jar" org.itstack.demo.jvm.Main -Xjre "C:\Program Files\Java\jdk1.8.0_161\jre" E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\test-classes\org\itstack\demo\test\HelloWorld
classpath:org.itstack.demo.jvm.classpath.Classpath@4bf558aa class:E:\itstack\git\istack-demo\itstack-demo-jvm\itstack-demo-jvm-05\target\test-classes\org\itstack\demo\test\HelloWorld args:null
寄存器(指令):0x03 -> ICONST_0 => 局部变量表:[{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0}]
寄存器(指令):0x3c -> ISTORE_1 => 局部变量表:[{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0}]
寄存器(指令):0x04 -> ICONST_1 => 局部变量表:[{"num":0},{"num":0}] 操作数栈:[{"num":0},{"num":0}]
寄存器(指令):0x3d -> ISTORE_2 => 局部变量表:[{"num":1},{"num":0}] 操作数栈:[{"num":1},{"num":0}]
寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":1},{"num":0}] 操作数栈:[{"num":1},{"num":0}]
寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":1},{"num":0}] 操作数栈:[{"num":1},{"num":0}]
寄存器(指令):0xa3 -> IF_ICMPGT => 局部变量表:[{"num":1},{"num":100}] 操作数栈:[{"num":1},{"num":100}]
寄存器(指令):0x1b -> ILOAD_1 => 局部变量表:[{"num":1},{"num":100}] 操作数栈:[{"num":1},{"num":100}]
寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":0},{"num":100}] 操作数栈:[{"num":0},{"num":100}]... ...寄存器(指令):0x60 -> IADD => 局部变量表:[{"num":4950},{"num":100}] 操作数栈:[{"num":4950},{"num":100}]
寄存器(指令):0x3c -> ISTORE_1 => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0x84 -> IINC => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0xa7 -> GOTO => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0x1c -> ILOAD_2 => 局部变量表:[{"num":5050},{"num":100}] 操作数栈:[{"num":5050},{"num":100}]
寄存器(指令):0x10 -> BIPUSH => 局部变量表:[{"num":101},{"num":100}] 操作数栈:[{"num":101},{"num":100}]
寄存器(指令):0xa3 -> IF_ICMPGT => 局部变量表:[{"num":101},{"num":100}] 操作数栈:[{"num":101},{"num":100}]
寄存器(指令)尚未实现 0xb2Process finished with exit code 0
用Java实现JVM第五章《指令集和解释器》相关推荐
- Java核心技术卷一 -第五章:装箱和拆箱
系列文章目录 Java核心技术卷一 -第一章:java"白皮书"的关键术语 Java核心技术卷一 -第三章:数据类型 Java核心技术卷一 -第三章:变量与常量 Java核心技术卷 ...
- Java核心技术卷一 -第五章:类的强制类型转换与instanceof操作符
系列文章目录 Java核心技术卷一 -第一章:java"白皮书"的关键术语 Java核心技术卷一 -第三章:数据类型 Java核心技术卷一 -第三章:变量与常量 Java核心技术卷 ...
- Java核心技术卷一 -第五章:枚举类再认识
系列文章目录 Java核心技术卷一 -第一章:java"白皮书"的关键术语 Java核心技术卷一 -第三章:数据类型 Java核心技术卷一 -第三章:变量与常量 Java核心技术卷 ...
- Java初级笔记-第五章
第五章 面向对象的特点 5.1 继承 面向对象的重要特点之一就是继承.类的继承使得能够在已有的类的基础上构造新的类,新类除了具有被继承类的属性和方法外,还可以根据需要添加新的属性和方法.继承有利于代码 ...
- Java基础一到五章复习笔记
目录 第一章 第二章 java语言特点 JDK和JRE 转义字符: 注释: 相对路径和绝对路径 常用dos命令 第三章 变量三要素: 加号+的使用: Java API 基本数据类型转换 强制类型转换 ...
- Java(第十五章)
第十五章 一.字符串类String 1.String是一个类,位于java.lang包中 2.创建一个字符串对象的2种方式: String 变量名="值"; String 对象名= ...
- 【JAVA SE】第五章 数组、多维数组和Arrays类
第五章 数组.多维数组和Arrays类 文章目录 第五章 数组.多维数组和Arrays类 一.数组 1.概述 2.声明数组变量 3.创建数组 4.For-Each 循环 二.多维数组 1.概述 2.多 ...
- Java学习 第十五章 成员变量和局部变量的区别 / 三大特征之一 (封装性)/构造方法 /private关键字
第十五章 局部变量和成员变量: 1.定义位置不一样 局部变量:在方法内部定义 成员变量:在方法的外部,直接写在类当中 2.作用范围不一样 局部变量:只能在方法当中使用 成员变量:整个类都可以使用 3. ...
- java for循环_愉快地学Java语言:第五章 循环
导读 本文适合Java入门,不太适合Java中高级软件工程师.本文以<Java程序设计基础篇>第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述.本篇文章只是这个系列中的一篇,如果 ...
- java第五章课后题_黑猴子的家:Java SE 练习题第五章
尾部都有答案 第五章练习题(继承) (1)下列关于继承优点的叙述正确的是哪几项?(选三项) A.可以创建更为特殊的类型 B.消除重复代码 C.执行效率高 D.便于维护 (2)在子类中调用父类中被覆盖的 ...
最新文章
- windows计算器
- 管理经验之没有必要的消费:空白卡片
- 对研发人员很有震撼和启发的公式
- 历史上的今天:编程语言中null引用的十亿美元错误
- linux怎么远程命令,Linux远程命令
- 常用的前端跨域的几种方式
- jQuery源码研究分析学习笔记-jQuery.fn.init()(五)
- Python入门之软件开发目录规范
- 【电子书分享】决战大数据-驾驭未来商业的利器.pdf(附下载链接)
- 回顾 | Apache Flink x TiDB Meetup · 北京站(附 PPT 下载)
- 电子申请客户端(EAC)在64位系统上的兼容性问题
- cad的文字嵌入线条_CAD字体如何转变为线条
- 金蝶KIS专业版本单据导入导出工具使用说明
- 笔记本触摸板操作手势
- 涉案金额2亿多!贺金虎、刘国庆非法吸收公众存款案开庭
- linux iptable配置
- 时间序列进行分析的一些手法以及代码实现(移动平均、指数平滑、SARIMA模型、时间序列的(非)线性模型)
- Redis Desktop Manager 黑屏
- String为什么要设计成final
- 2年java开发工作经验