这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
简介
Java虚拟机顾名思义,就是一台虚拟的机器,而字节码(bytecode)就是运行在这台虚拟机器上的机器码。我们已经知道,每一个类或者接口都会被Java编译器编译成一个class文件,类或接口的方法信息就放在class文件的method_info结构中。

Java字节码指令大全
指令工厂
具体指令可查阅docs.oracle.com/javase/spec…
package com.black.cat.jvm.instructions;
import com.black.cat.jvm.instructions.base.Instruction;
import com.black.cat.jvm.instructions.comparisons.dcmp.DCMPG;
import com.black.cat.jvm.instructions.comparisons.dcmp.DCMPL;
import com.black.cat.jvm.instructions.comparisons.fcmp.FCMPG;
import com.black.cat.jvm.instructions.comparisons.fcmp.FCMPL;
import com.black.cat.jvm.instructions.comparisons.if_acmp.IF_ACMPEQ;
import com.black.cat.jvm.instructions.comparisons.if_acmp.IF_ACMPNE;
import com.black.cat.jvm.instructions.comparisons.if_icmp.*;
import com.black.cat.jvm.instructions.comparisons.ifcond.*;
import com.black.cat.jvm.instructions.comparisons.lcmp.LCMP;
import com.black.cat.jvm.instructions.constants.consts.*;
import com.black.cat.jvm.instructions.constants.ipush.BIPUSH;
import com.black.cat.jvm.instructions.constants.ipush.SIPUSH;
import com.black.cat.jvm.instructions.constants.nop.NOP;
import com.black.cat.jvm.instructions.control.GOTO;
import com.black.cat.jvm.instructions.control.LOOKUP_SWITCH;
import com.black.cat.jvm.instructions.control.TABLE_SWITCH;
import com.black.cat.jvm.instructions.conversions.d2x.D2F;
import com.black.cat.jvm.instructions.conversions.d2x.D2I;
import com.black.cat.jvm.instructions.conversions.d2x.D2L;
import com.black.cat.jvm.instructions.conversions.f2x.F2D;
import com.black.cat.jvm.instructions.conversions.f2x.F2I;
import com.black.cat.jvm.instructions.conversions.f2x.F2L;
import com.black.cat.jvm.instructions.conversions.i2x.*;
import com.black.cat.jvm.instructions.conversions.l2x.L2D;
import com.black.cat.jvm.instructions.conversions.l2x.L2F;
import com.black.cat.jvm.instructions.conversions.l2x.L2I;
import com.black.cat.jvm.instructions.extended.GOTO_W;
import com.black.cat.jvm.instructions.extended.WIDE;
import com.black.cat.jvm.instructions.extended.ifnull.IFNONNULL;
import com.black.cat.jvm.instructions.extended.ifnull.IFNULL;
import com.black.cat.jvm.instructions.loads.aload.*;
import com.black.cat.jvm.instructions.loads.dload.*;
import com.black.cat.jvm.instructions.loads.fload.*;
import com.black.cat.jvm.instructions.loads.iload.*;
import com.black.cat.jvm.instructions.loads.lload.*;
import com.black.cat.jvm.instructions.math.add.DADD;
import com.black.cat.jvm.instructions.math.add.FADD;
import com.black.cat.jvm.instructions.math.add.IADD;
import com.black.cat.jvm.instructions.math.add.LADD;
import com.black.cat.jvm.instructions.math.and.IAND;
import com.black.cat.jvm.instructions.math.and.LAND;
import com.black.cat.jvm.instructions.math.div.DDIV;
import com.black.cat.jvm.instructions.math.div.FDIV;
import com.black.cat.jvm.instructions.math.div.IDIV;
import com.black.cat.jvm.instructions.math.div.LDIV;
import com.black.cat.jvm.instructions.math.iinc.IINC;
import com.black.cat.jvm.instructions.math.mul.DMUL;
import com.black.cat.jvm.instructions.math.mul.FMUL;
import com.black.cat.jvm.instructions.math.mul.IMUL;
import com.black.cat.jvm.instructions.math.mul.LMUL;
import com.black.cat.jvm.instructions.math.neg.DNEG;
import com.black.cat.jvm.instructions.math.neg.FNEG;
import com.black.cat.jvm.instructions.math.neg.INEG;
import com.black.cat.jvm.instructions.math.neg.LNEG;
import com.black.cat.jvm.instructions.math.or.IOR;
import com.black.cat.jvm.instructions.math.or.LOR;
import com.black.cat.jvm.instructions.math.rem.DREM;
import com.black.cat.jvm.instructions.math.rem.FREM;
import com.black.cat.jvm.instructions.math.rem.IREM;
import com.black.cat.jvm.instructions.math.rem.LREM;
import com.black.cat.jvm.instructions.math.sh.*;
import com.black.cat.jvm.instructions.math.sub.DSUB;
import com.black.cat.jvm.instructions.math.sub.FSUB;
import com.black.cat.jvm.instructions.math.sub.ISUB;
import com.black.cat.jvm.instructions.math.sub.LSUB;
import com.black.cat.jvm.instructions.math.xor.IXOR;
import com.black.cat.jvm.instructions.math.xor.LXOR;
import com.black.cat.jvm.instructions.stack.dup.*;
import com.black.cat.jvm.instructions.stack.pop.POP;
import com.black.cat.jvm.instructions.stack.pop.POP2;
import com.black.cat.jvm.instructions.stack.swap.SWAP;
import com.black.cat.jvm.instructions.stores.astore.*;
import com.black.cat.jvm.instructions.stores.dstore.*;
import com.black.cat.jvm.instructions.stores.fstore.*;
import com.black.cat.jvm.instructions.stores.istore.*;
import com.black.cat.jvm.instructions.stores.lstore.*;
public class InstructionFactory {
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 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 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 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 (byte) 0xaa:
return new TABLE_SWITCH();
case (byte) 0xab:
return new LOOKUP_SWITCH();
case (byte) 0xc4:
return new WIDE();
case (byte) 0xc6:
return new IFNULL();
case (byte) 0xc7:
return new IFNONNULL();
case (byte) 0xc8:
return new GOTO_W();
default:
return null;
}
}
}
常量指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x01 | aconst_null | | null值入栈。 |
| 0x02 | iconst_m1 | | -1(int)值入栈。 |
| 0x03 | iconst_0 | | 0(int)值入栈。 |
| 0x04 | iconst_1 | | 1(int)值入栈。 |
| 0x05 | iconst_2 | | 2(int)值入栈。 |
| 0x06 | iconst_3 | | 3(int)值入栈。 |
| 0x07 | iconst_4 | | 4(int)值入栈。 |
| 0x08 | iconst_5 | | 5(int)值入栈。 |
| 0x09 | lconst_0 | | 0(long)值入栈。 |
| 0x0a | lconst_1 | | 1(long)值入栈。 |
| 0x0b | fconst_0 | | 0(float)值入栈。 |
| 0x0c | fconst_1 | | 1(float)值入栈。 |
| 0x0d | fconst_2 | | 2(float)值入栈。 |
| 0x0e | dconst_0 | | 0(double)值入栈。 |
| 0x0f | dconst_1 | | 1(double)值入栈。 |
| 0x10 | bipush | valuebyte | valuebyte值带符号扩展成int值入栈。 |
| 0x11 | sipush | valuebyte1valuebyte2 | (valuebyte1 << 8) | valuebyte2 值带符号扩展成int值入栈。 |
| 0x12 | ldc | indexbyte1 | 常量池中的常量值(int, float, string reference, object reference)入栈。 |
| 0x13 | ldc_w | indexbyte1indexbyte2 | 常量池中常量(int, float, string reference, object reference)入栈。 |
| 0x14 | ldc2_w | indexbyte1indexbyte2 | 常量池中常量(long, double)入栈。 |
存储指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x3a | (wide)astore | indexbyte | 将栈顶引用类型值保存到局部变量indexbyte中。 |
| 0x4b | astroe_0 | | 将栈顶引用类型值保存到局部变量0中。 |
| 0x4c | astore_1 | | 将栈顶引用类型值保存到局部变量1中。 |
| 0x4d | astore_2 | | 将栈顶引用类型值保存到局部变量2中。 |
| 0x4e | astore_3 | | 将栈顶引用类型值保存到局部变量3中。 |
| 0x36 | (wide)istore | indexbyte | 将栈顶int类型值保存到局部变量indexbyte中。 |
| 0x3b | istore_0 | | 将栈顶int类型值保存到局部变量0中。 |
| 0x3c | istore_1 | | 将栈顶int类型值保存到局部变量1中。 |
| 0x3d | istore_2 | | 将栈顶int类型值保存到局部变量2中。 |
| 0x3e | istore_3 | | 将栈顶int类型值保存到局部变量3中。 |
| 0x37 | (wide)lstore | indexbyte | 将栈顶long类型值保存到局部变量indexbyte中。 |
| 0x3f | lstore_0 | | 将栈顶long类型值保存到局部变量0中。 |
| 0x40 | lstore_1 | | 将栈顶long类型值保存到局部变量1中。 |
| 0x41 | lstore_2 | | 将栈顶long类型值保存到局部变量2中。 |
| 0x42 | lstroe_3 | | 将栈顶long类型值保存到局部变量3中。 |
| 0x38 | (wide)fstore | indexbyte | 将栈顶float类型值保存到局部变量indexbyte中。 |
| 0x43 | fstore_0 | | 将栈顶float类型值保存到局部变量0中。 |
| 0x44 | fstore_1 | | 将栈顶float类型值保存到局部变量1中。 |
| 0x45 | fstore_2 | | 将栈顶float类型值保存到局部变量2中。 |
| 0x46 | fstore_3 | | 将栈顶float类型值保存到局部变量3中。 |
| 0x39 | (wide)dstore | indexbyte | 将栈顶double类型值保存到局部变量indexbyte中。 |
| 0x47 | dstore_0 | | 将栈顶double类型值保存到局部变量0中。 |
| 0x48 | dstore_1 | | 将栈顶double类型值保存到局部变量1中。 |
| 0x49 | dstore_2 | | 将栈顶double类型值保存到局部变量2中。 |
| 0x4a | dstore_3 | | 将栈顶double类型值保存到局部变量3中。 |
| 0x53 | aastore | | 将栈顶引用类型值保存到指定引用类型数组的指定项。 |
| 0x4f | iastore | | 将栈顶int类型值保存到指定int类型数组的指定项。 |
| 0x50 | lastore | | 将栈顶long类型值保存到指定long类型数组的指定项。 |
| 0x51 | fastore | | 将栈顶float类型值保存到指定float类型数组的指定项。 |
| 0x52 | dastore | | 将栈顶double类型值保存到指定double类型数组的指定项。 |
| 0x54 | bastroe | | 将栈顶boolean类型值或byte类型值保存到指定boolean类型数组或byte类型数组的指定项。 |
| 0x55 | castore | | 将栈顶char类型值保存到指定char类型数组的指定项。 |
| 0x56 | sastore | | 将栈顶short类型值保存到指定short类型数组的指定项。 |
栈操作指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x00 | nop | | 空操作。 |
| 0x57 | pop | | 从栈顶弹出一个字长的数据。 |
| 0x58 | pop2 | | 从栈顶弹出两个字长的数据。 |
| 0x59 | dup | | 复制栈顶一个字长的数据,将复制后的数据压栈。 |
| 0x5a | dup_x1 | | 复制栈顶一个字长的数据,弹出栈顶两个字长数据,先将复制后的数据压栈,再将弹出的两个字长数据压栈。 |
| 0x5b | dup_x2 | | 复制栈顶一个字长的数据,弹出栈顶三个字长的数据,将复制后的数据压栈,再将弹出的三个字长的数据压栈。 |
| 0x5c | dup2 | | 复制栈顶两个字长的数据,将复制后的两个字长的数据压栈。 |
| 0x5d | dup2_x1 | | 复制栈顶两个字长的数据,弹出栈顶三个字长的数据,将复制后的两个字长的数据压栈,再将弹出的三个字长的数据压栈。 |
| 0x5e | dup2_x2 | | 复制栈顶两个字长的数据,弹出栈顶四个字长的数据,将复制后的两个字长的数据压栈,再将弹出的四个字长的数据压栈。 |
| 0x5f | swap | | 交换栈顶两个字长的数据的位置。Java指令中没有提供以两个字长为单位的交换指令。 |
算术指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x60 | iadd | | 将栈顶两int类型数相加,结果入栈。 |
| 0x64 | isub | | 将栈顶两int类型数相减,结果入栈。 |
| 0x68 | imul | | 将栈顶两int类型数相乘,结果入栈。 |
| 0x6c | idiv | | 将栈顶两int类型数相除,结果入栈。 |
| 0x70 | irem | | 将栈顶两int类型数取模,结果入栈。 |
| 0x74 | ineg | | 将栈顶int类型值取负,结果入栈。 |
| 0x61 | ladd | | 将栈顶两long类型数相加,结果入栈。 |
| 0x65 | lsub | | 将栈顶两long类型数相减,结果入栈。 |
| 0x69 | lmul | | 将栈顶两long类型数相乘,结果入栈。 |
| 0x6d | ldiv | | 将栈顶两long类型数相除,结果入栈。 |
| 0x71 | lrem | | 将栈顶两long类型数取模,结果入栈。 |
| 0x75 | lneg | | 将栈顶long类型值取负,结果入栈。 |
| 0x84 | (wide)iinc | indexbyteconstbyte | 将整数值constbyte加到indexbyte指定的int类型的局部变量中。 |
类型转换指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x86 | i2f | | 将栈顶int类型值转换为float类型值。 |
| 0x85 | i2l | | 将栈顶int类型值转换为long类型值。 |
| 0x87 | i2d | | 将栈顶int类型值转换为double类型值。 |
| 0x8b | f2i | | 将栈顶float类型值转换为int类型值。 |
| 0x8c | f2l | | 将栈顶float类型值转换为long类型值。 |
| 0x8d | f2d | | 将栈顶float类型值转换为double类型值。 |
| 0x88 | l2i | | 将栈顶long类型值转换为int类型值。 |
| 0x89 | l2f | | 将栈顶long类型值转换为float类型值。 |
| 0x8a | l2d | | 将栈顶long类型值转换double类型值。 |
| 0x8e | d2i | | 将栈顶double类型值转换为int类型值。 |
| 0x90 | d2f | | 将栈顶double类型值转换为float类型值。 |
| 0x8f | d2l | | 将栈顶double类型值转换为long类型值。 |
| 0x91 | i2b | | 将栈顶int类型值截断成byte类型,后带符号扩展成int类型值入栈。 |
| 0x92 | i2c | | 将栈顶int类型值截断成char类型值,后带符号扩展成int类型值入栈。 |
| 0x93 | i2s | | 将栈顶int类型值截断成short类型值,后带符号扩展成int类型值入栈。 |
比较指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x94 | lcmp | | 比较栈顶两long类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈。 |
| 0x95 | fcmpl | | 比较栈顶两float类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈。 |
| 0x96 | fcmpg | | 比较栈顶两float类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈。 |
| 0x97 | dcmpl | | 比较栈顶两double类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈。 |
| 0x98 | dcmpg | | 比较栈顶两double类型值,前者大,1入栈;相等,0入栈;后者大,-1入栈;有NaN存在,-1入栈。 |
控制指令
| 指令码 | 操作码(助记符) | 操作数 | 描述(栈指操作数栈) |
|---|
| 0x99 | ifeq | branchbyte1branchbyte2 | 若栈顶int类型值为0则跳转。 |
| 0x9a | ifne | branchbyte1branchbyte2 | 若栈顶int类型值不为0则跳转。 |
| 0x9b | iflt | branchbyte1branchbyte2 | 若栈顶int类型值小于0则跳转。 |
| 0x9e | ifle | branchbyte1branchbyte2 | 若栈顶int类型值小于等于0则跳转。 |
| 0x9d | ifgt | branchbyte1branchbyte2 | 若栈顶int类型值大于0则跳转。 |
| 0x9c | ifge | branchbyte1branchbyte2 | 若栈顶int类型值大于等于0则跳转。 |
| 0x9f | if_icmpeq | branchbyte1branchbyte2 | 若栈顶两int类型值相等则跳转。 |
| 0xa0 | if_icmpne | branchbyte1branchbyte2 | 若栈顶两int类型值不相等则跳转。 |
| 0xa1 | if_icmplt | branchbyte1branchbyte2 | 若栈顶两int类型值前小于后则跳转。 |
| 0xa4 | if_icmple | branchbyte1branchbyte2 | 若栈顶两int类型值前小于等于后则跳转。 |
| 0xa3 | if_icmpgt | branchbyte1branchbyte2 | 若栈顶两int类型值前大于后则跳转。 |
| 0xa2 | if_icmpge | branchbyte1branchbyte2 | 若栈顶两int类型值前大于等于后则跳转。 |
| 0xc6 | ifnull | branchbyte1branchbyte2 | 若栈顶引用值为null则跳转。 |
| 0xc7 | ifnonnull | branchbyte1branchbyte2 | 若栈顶引用值不为null则跳转。 |
| 0xa5 | if_acmpeq | branchbyte1branchbyte2 | 若栈顶两引用类型值相等则跳转。 |
| 0xa6 | if_acmpne | branchbyte1branchbyte2 | 若栈顶两引用类型值不相等则跳转。 |
部分代码
package com.black.cat.jvm;
import com.alibaba.fastjson.JSON;
import com.black.cat.jvm.classfile.MemberInfo;
import com.black.cat.jvm.classfile.attribute.CodeAttribute;
import com.black.cat.jvm.instructions.InstructionFactory;
import com.black.cat.jvm.instructions.base.BytecodeReader;
import com.black.cat.jvm.instructions.base.Instruction;
import com.black.cat.jvm.rtda.Frame;
import com.black.cat.jvm.rtda.JThread;
import java.util.Arrays;
public class Interpret {
Interpret(MemberInfo m) {
CodeAttribute codeAttr = m.codeAttribute();
int maxLocals = codeAttr.getMaxLocals();
int maxStack = codeAttr.getMaxStack();
byte[] byteCode = codeAttr.getCode();
JThread thread = new JThread();
Frame frame = thread.newFrame(maxLocals, maxStack);
thread.pushFrame(frame);
loop(thread, byteCode);
}
private void loop(JThread thread, byte[] byteCode) {
Frame frame = thread.popFrame();
BytecodeReader reader = new BytecodeReader();
while (true) {
int pc = frame.nextPC();
thread.setPC(pc);
reader.reset(byteCode, pc);
byte opcode = reader.readByte();
Instruction inst = InstructionFactory.newInstruction(opcode);
if (null == inst) {
System.out.println("寄存器(指令)尚未实现 " + byteToHexString(new byte[]{opcode}));
break;
}
inst.fetchOperands(reader);
frame.setNextPC(reader.getPC());
System.out.println("pc:" + pc + " -> " + "寄存器(指令):" + byteToHexString(new byte[]{opcode}) + " -> " + inst.getClass().getSimpleName() + " => 局部变量表:" + Arrays.toString(frame.localVars().getSlots()) + " 操作数栈:" + Arrays.toString(frame.operandStack().getSlots()));
inst.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();
}
}
package com.black.cat.jvm;
import com.black.cat.jvm.classfile.ClassFile;
import com.black.cat.jvm.classfile.MemberInfo;
import com.black.cat.jvm.classpath.Classpath;
import com.black.cat.jvm.rtda.Frame;
import com.black.cat.jvm.rtda.LocalVars;
import com.black.cat.jvm.rtda.OperandStack;
public class Main {
public static void main(String[] args) {
String[] argv = {"-classpath", "D:\\develop\\code\\jjvm\\jvm-05\\target\\classes", "com.black.cat.jvm.MainTest"};
Cmd cmd = Cmd.parse(argv);
if (!cmd.ok || cmd.helpFlag) {
System.out.println("Usage: <main class> [-options] class [args...]");
return;
}
if (cmd.versionFlag) {
System.out.println("java version \"1.8.0\"");
return;
}
startJVM(cmd);
}
private static void startJVM(Cmd cmd) {
Classpath classpath = new Classpath(cmd.jre, cmd.classpath);
System.out.printf("classpath:%s class:%s args:%s\n", classpath, cmd.getMainClass(), cmd.getAppArgs());
String className = cmd.getMainClass().replace(".", "/");
ClassFile classFile = loadClass(className, classpath);
MemberInfo mainMethod = getMainMethod(classFile);
if (null == mainMethod) {
System.out.println("Main method not found in class " + cmd.classpath);
return;
}
new Interpret(mainMethod);
}
private static ClassFile loadClass(String className, Classpath cp) {
try {
byte[] classData = cp.readClass(className);
return new ClassFile(classData);
} catch (Exception e) {
System.out.println("Could not find or load main class " + className);
e.printStackTrace();
}
return null;
}
private static MemberInfo getMainMethod(ClassFile cf) {
if (null == cf) return null;
MemberInfo[] methods = cf.getMethodInfos();
for (MemberInfo m : methods) {
if ("main".equals(m.name()) && "([Ljava/lang/String;)V".equals(m.descriptor())) {
return m;
}
}
return null;
}
}
package com.black.cat.jvm;
import java.io.IOException;
public class MainTest {
public static void main(String[] args) throws IOException {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println(sum);
}
}
测试

gitee 地址
gitee.com/feicc/jjvm/…