用Java实现JVM第五章《指令集和解释器》
案例介紹
本案例通過(guò)java代碼實(shí)現(xiàn)jvm規(guī)范中指令集和解釋器,完成后就可以開(kāi)始執(zhí)行1到100的加和計(jì)算。
Java虛擬機(jī)顧名思義,就是一臺(tái)虛擬的機(jī)器,而字節(jié)碼(bytecode)就是運(yùn)行在這臺(tái)虛擬機(jī)器上的機(jī)器碼。我們已經(jīng)知道,每一個(gè)類或者接口都會(huì)被Java編譯器編譯成一個(gè)class文件,類或接口的方法信息就放在class文件的method_info結(jié)構(gòu)中。如果方法不是抽象的,也不是本地方法,方法的Java代碼就會(huì)被編譯器編譯成字節(jié)碼(即使方法是空的,編譯器也會(huì)生成一條return語(yǔ)句),存在method_info結(jié)構(gòu)的Code屬性中。
環(huán)境準(zhǔn)備
1、jdk 1.8.0
2、IntelliJ IDEA Community Edition 2018.3.1 x64
配置信息
1、調(diào)試配置
2.1、配置位置:Run/Debug Configurations -> program arguments
2.2、配置內(nèi)容:-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.javaFactory.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) {//循環(huán)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("寄存器(指令)尚未實(shí)現(xiàn) " + 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()) + " 操作數(shù)棧:" + 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);}}測(cè)試結(jié)果 {此時(shí)還不能輸出結(jié)果,但是在操作數(shù)據(jù)棧中已經(jīng)可以看到結(jié)果: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}] 操作數(shù)棧:[{"num":0},{"num":0}] 寄存器(指令):0x3c -> ISTORE_1 => 局部變量表:[{"num":0},{"num":0}] 操作數(shù)棧:[{"num":0},{"num":0}] 寄存器(指令):0x04 -> ICONST_1 => 局部變量表:[{"num":0},{"num":0}] 操作數(shù)棧:[{"num":0},{"num":0}] 寄存器(指令):0x3d -> ISTORE_2 => 局部變量表:[{"num":1},{"num":0}] 操作數(shù)棧:[{"num":1},{"num":0}] 寄存器(指令):0x1c -> ILOAD_2 => 局部變量表:[{"num":1},{"num":0}] 操作數(shù)棧:[{"num":1},{"num":0}] 寄存器(指令):0x10 -> BIPUSH => 局部變量表:[{"num":1},{"num":0}] 操作數(shù)棧:[{"num":1},{"num":0}] 寄存器(指令):0xa3 -> IF_ICMPGT => 局部變量表:[{"num":1},{"num":100}] 操作數(shù)棧:[{"num":1},{"num":100}] 寄存器(指令):0x1b -> ILOAD_1 => 局部變量表:[{"num":1},{"num":100}] 操作數(shù)棧:[{"num":1},{"num":100}] 寄存器(指令):0x1c -> ILOAD_2 => 局部變量表:[{"num":0},{"num":100}] 操作數(shù)棧:[{"num":0},{"num":100}]... ...寄存器(指令):0x60 -> IADD => 局部變量表:[{"num":4950},{"num":100}] 操作數(shù)棧:[{"num":4950},{"num":100}] 寄存器(指令):0x3c -> ISTORE_1 => 局部變量表:[{"num":5050},{"num":100}] 操作數(shù)棧:[{"num":5050},{"num":100}] 寄存器(指令):0x84 -> IINC => 局部變量表:[{"num":5050},{"num":100}] 操作數(shù)棧:[{"num":5050},{"num":100}] 寄存器(指令):0xa7 -> GOTO => 局部變量表:[{"num":5050},{"num":100}] 操作數(shù)棧:[{"num":5050},{"num":100}] 寄存器(指令):0x1c -> ILOAD_2 => 局部變量表:[{"num":5050},{"num":100}] 操作數(shù)棧:[{"num":5050},{"num":100}] 寄存器(指令):0x10 -> BIPUSH => 局部變量表:[{"num":101},{"num":100}] 操作數(shù)棧:[{"num":101},{"num":100}] 寄存器(指令):0xa3 -> IF_ICMPGT => 局部變量表:[{"num":101},{"num":100}] 操作數(shù)棧:[{"num":101},{"num":100}] 寄存器(指令)尚未實(shí)現(xiàn) 0xb2Process finished with exit code 0總結(jié)
以上是生活随笔為你收集整理的用Java实现JVM第五章《指令集和解释器》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 自动化测试工具-Airtest
- 下一篇: mysql源码解读——事务管理