├── .gitignore ├── Java └── src │ ├── Main.java │ ├── Utils │ ├── ByteUtils.java │ └── Cmd.java │ ├── classfile │ ├── ClassFile.java │ ├── ClassReader.java │ ├── ConstantPool.java │ ├── MemberInfo.java │ ├── attribute │ │ ├── AttributeInfo.java │ │ ├── CodeAttribute.java │ │ ├── ConstantValueAttribute.java │ │ ├── DeprecatedAttribute.java │ │ ├── ExceptionsAttribute.java │ │ ├── LineNumberTableAttribute.java │ │ ├── LocalVariableTableAttribute.java │ │ ├── SourceFileAttribute.java │ │ ├── SyntheticAttribute.java │ │ └── UnparsedAttribute.java │ └── classconstant │ │ ├── ConstantClassInfo.java │ │ ├── ConstantDoubleInfo.java │ │ ├── ConstantFieldRefInfo.java │ │ ├── ConstantFloatInfo.java │ │ ├── ConstantInfo.java │ │ ├── ConstantIntegerInfo.java │ │ ├── ConstantInterfaceMethodRefInfo.java │ │ ├── ConstantInvokeDynamicInfo.java │ │ ├── ConstantLongInfo.java │ │ ├── ConstantMemberRefInfo.java │ │ ├── ConstantMethodHandleInfo.java │ │ ├── ConstantMethodRefInfo.java │ │ ├── ConstantMethodTypeInfo.java │ │ ├── ConstantNameAndTypeInfo.java │ │ ├── ConstantStringInfo.java │ │ └── ConstantUtf8Info.java │ ├── classpath │ ├── ClassPath.java │ ├── CompositeEntry.java │ ├── DirEntry.java │ ├── Entry.java │ ├── WildcardEntry.java │ └── ZipJarEntry.java │ ├── instructions │ ├── InstructionFactory.java │ ├── base │ │ ├── BranchInstruction.java │ │ ├── BranchLogic.java │ │ ├── BytecodeReader.java │ │ ├── ClassInitLogic.java │ │ ├── Index16Instruction.java │ │ ├── Index8Instruction.java │ │ ├── Instruction.java │ │ ├── MethodInvokeLogic.java │ │ └── NoOperandsInstruction.java │ ├── comparisons │ │ ├── dcmp │ │ │ ├── DCMP.java │ │ │ ├── DCMPG.java │ │ │ └── DCMPL.java │ │ ├── fcmp │ │ │ ├── FCMP.java │ │ │ ├── FCMPG.java │ │ │ └── FCMPL.java │ │ ├── ifacmp │ │ │ ├── IF_ACMPEQ.java │ │ │ ├── IF_ACMPNE.java │ │ │ └── IfAcmp.java │ │ ├── ifcond │ │ │ ├── IFEQ.java │ │ │ ├── IFGE.java │ │ │ ├── IFGT.java │ │ │ ├── IFLE.java │ │ │ ├── IFLT.java │ │ │ └── IFNE.java │ │ ├── ificmp │ │ │ ├── IF_ICMPEQ.java │ │ │ ├── IF_ICMPGE.java │ │ │ ├── IF_ICMPGT.java │ │ │ ├── IF_ICMPLE.java │ │ │ ├── IF_ICMPLT.java │ │ │ ├── IF_ICMPNE.java │ │ │ └── IfIcmp.java │ │ └── lcmp │ │ │ └── LCMP.java │ ├── constants │ │ ├── ACONST_NULL.java │ │ ├── BIPUSH.java │ │ ├── DCONST_0.java │ │ ├── DCONST_1.java │ │ ├── FCONST_0.java │ │ ├── FCONST_1.java │ │ ├── FCONST_2.java │ │ ├── ICONST_0.java │ │ ├── ICONST_1.java │ │ ├── ICONST_2.java │ │ ├── ICONST_3.java │ │ ├── ICONST_4.java │ │ ├── ICONST_5.java │ │ ├── ICONST_M1.java │ │ ├── LCONST_0.java │ │ ├── LCONST_1.java │ │ ├── LDC.java │ │ ├── LDC2_W.java │ │ ├── LDC_W.java │ │ ├── NOP.java │ │ └── SIPUSH.java │ ├── control │ │ ├── ARETURN.java │ │ ├── DRETURN.java │ │ ├── FRETURN.java │ │ ├── GOTO.java │ │ ├── IRETURN.java │ │ ├── LOOKUP_SWITCH.java │ │ ├── LRETURN.java │ │ ├── RETURN.java │ │ └── TABLE_SWITCH.java │ ├── conversions │ │ ├── d2x │ │ │ ├── D2F.java │ │ │ ├── D2I.java │ │ │ └── D2L.java │ │ ├── f2x │ │ │ ├── F2D.java │ │ │ ├── F2I.java │ │ │ └── F2L.java │ │ ├── i2x │ │ │ ├── I2B.java │ │ │ ├── I2C.java │ │ │ ├── I2D.java │ │ │ ├── I2F.java │ │ │ ├── I2L.java │ │ │ └── I2S.java │ │ └── l2x │ │ │ ├── L2D.java │ │ │ ├── L2F.java │ │ │ └── L2I.java │ ├── extended │ │ ├── GOTO_W.java │ │ ├── IFNONNULL.java │ │ ├── IFNULL.java │ │ └── WIDE.java │ ├── loads │ │ ├── Load.java │ │ ├── loaddouble │ │ │ ├── DLOAD.java │ │ │ ├── DLOAD_0.java │ │ │ ├── DLOAD_1.java │ │ │ ├── DLOAD_2.java │ │ │ └── DLOAD_3.java │ │ ├── loadfloat │ │ │ ├── FLOAD.java │ │ │ ├── FLOAD_0.java │ │ │ ├── FLOAD_1.java │ │ │ ├── FLOAD_2.java │ │ │ └── FLOAD_3.java │ │ ├── loadint │ │ │ ├── ILOAD.java │ │ │ ├── ILOAD_0.java │ │ │ ├── ILOAD_1.java │ │ │ ├── ILOAD_2.java │ │ │ └── ILOAD_3.java │ │ ├── loadlong │ │ │ ├── LLOAD.java │ │ │ ├── LLOAD_0.java │ │ │ ├── LLOAD_1.java │ │ │ ├── LLOAD_2.java │ │ │ └── LLOAD_3.java │ │ ├── loadref │ │ │ ├── ALOAD.java │ │ │ ├── ALOAD_0.java │ │ │ ├── ALOAD_1.java │ │ │ ├── ALOAD_2.java │ │ │ └── ALOAD_3.java │ │ └── loadxarr │ │ │ ├── AALOAD.java │ │ │ ├── BALOAD.java │ │ │ ├── CALOAD.java │ │ │ ├── DALOAD.java │ │ │ ├── FALOAD.java │ │ │ ├── IALOAD.java │ │ │ ├── LALOAD.java │ │ │ └── SALOAD.java │ ├── math │ │ ├── add │ │ │ ├── DADD.java │ │ │ ├── FADD.java │ │ │ ├── IADD.java │ │ │ └── LADD.java │ │ ├── and │ │ │ ├── IAND.java │ │ │ └── LAND.java │ │ ├── div │ │ │ ├── DDIV.java │ │ │ ├── FDIV.java │ │ │ ├── IDIV.java │ │ │ └── LDIV.java │ │ ├── iinc │ │ │ └── IINC.java │ │ ├── mul │ │ │ ├── DMUL.java │ │ │ ├── FMUL.java │ │ │ ├── IMUL.java │ │ │ └── LMUL.java │ │ ├── neg │ │ │ ├── DNEG.java │ │ │ ├── FNEG.java │ │ │ ├── INEG.java │ │ │ └── LNEG.java │ │ ├── or │ │ │ ├── IOR.java │ │ │ └── LOR.java │ │ ├── rem │ │ │ ├── DREM.java │ │ │ ├── FREM.java │ │ │ ├── IREM.java │ │ │ └── LREM.java │ │ ├── sh │ │ │ ├── ISHL.java │ │ │ ├── ISHR.java │ │ │ ├── IUSHR.java │ │ │ ├── LSHL.java │ │ │ ├── LSHR.java │ │ │ └── LUSHR.java │ │ ├── sub │ │ │ ├── DSUB.java │ │ │ ├── FSUB.java │ │ │ ├── ISUB.java │ │ │ └── LSUB.java │ │ └── xor │ │ │ ├── IXOR.java │ │ │ └── LXOR.java │ ├── references │ │ ├── ANEW_ARRAY.java │ │ ├── ARRAY_LENGTH.java │ │ ├── ATHROW.java │ │ ├── CHECK_CAST.java │ │ ├── GET_FIELD.java │ │ ├── GET_STATIC.java │ │ ├── INSTANCE_OF.java │ │ ├── INVOKE_INTERFACE.java │ │ ├── INVOKE_NATIVE.java │ │ ├── INVOKE_SPECIAL.java │ │ ├── INVOKE_STATIC.java │ │ ├── INVOKE_VIRTUAL.java │ │ ├── MULTI_ANEW_ARRAY.java │ │ ├── NEW.java │ │ ├── NEW_ARRAY.java │ │ ├── PUT_FIELD.java │ │ └── PUT_STATIC.java │ ├── stack │ │ ├── dup │ │ │ ├── DUP.java │ │ │ ├── DUP2.java │ │ │ ├── DUP2_X1.java │ │ │ ├── DUP2_X2.java │ │ │ ├── DUP_X1.java │ │ │ └── DUP_X2.java │ │ ├── pop │ │ │ ├── POP.java │ │ │ └── POP2.java │ │ └── swap │ │ │ └── SWAP.java │ └── stores │ │ ├── Store.java │ │ ├── storedouble │ │ ├── DSTORE.java │ │ ├── DSTORE_0.java │ │ ├── DSTORE_1.java │ │ ├── DSTORE_2.java │ │ └── DSTORE_3.java │ │ ├── storefloat │ │ ├── FSTORE.java │ │ ├── FSTORE_0.java │ │ ├── FSTORE_1.java │ │ ├── FSTORE_2.java │ │ └── FSTORE_3.java │ │ ├── storeint │ │ ├── ISTORE.java │ │ ├── ISTORE_0.java │ │ ├── ISTORE_1.java │ │ ├── ISTORE_2.java │ │ └── ISTORE_3.java │ │ ├── storelong │ │ ├── LSTORE.java │ │ ├── LSTORE_0.java │ │ ├── LSTORE_1.java │ │ ├── LSTORE_2.java │ │ └── LSTORE_3.java │ │ ├── storeref │ │ ├── ASTORE.java │ │ ├── ASTORE_0.java │ │ ├── ASTORE_1.java │ │ ├── ASTORE_2.java │ │ └── ASTORE_3.java │ │ └── storexarr │ │ ├── AASTORE.java │ │ ├── BASTORE.java │ │ ├── CASTORE.java │ │ ├── DASTORE.java │ │ ├── FASTORE.java │ │ ├── IASTORE.java │ │ ├── LASTORE.java │ │ └── SASTORE.java │ ├── runtimedata │ ├── LocalVars.java │ ├── OperandStack.java │ ├── Slot.java │ ├── Slots.java │ ├── Zframe.java │ ├── Zstack.java │ ├── Zthread.java │ └── heap │ │ ├── AccessFlag.java │ │ ├── ClassMember.java │ │ ├── ClassNameHelper.java │ │ ├── ClassRef.java │ │ ├── ExceptionTable.java │ │ ├── FieldRef.java │ │ ├── InterfaceMethodRef.java │ │ ├── MemberRef.java │ │ ├── MethodDescriptor.java │ │ ├── MethodLookup.java │ │ ├── MethodRef.java │ │ ├── RuntimeConstantInfo.java │ │ ├── RuntimeConstantPool.java │ │ ├── StringPool.java │ │ ├── SymRef.java │ │ ├── Zclass.java │ │ ├── ZclassLoader.java │ │ ├── Zfield.java │ │ ├── Zmethod.java │ │ └── Zobject.java │ ├── test │ ├── TestClassFile03.java │ ├── TestClassLoader07.java │ ├── TestClassPath02.java │ ├── TestCmd01.java │ ├── TestException12.java │ ├── TestGetClass11.java │ ├── TestInterpreter06.java │ ├── TestInvokeMethod08.java │ ├── TestLocalVars04.java │ ├── TestNewArray09.java │ ├── TestOperandStack05.java │ └── TestStringPool10.java │ └── znative │ ├── NativeMethod.java │ ├── RegisterCenter.java │ └── java │ └── lang │ ├── NStackTraceElement.java │ ├── Nclass.java │ ├── Nobject.java │ └── Nthrowable.java └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | /local.properties 3 | /.idea/ 4 | /out 5 | .DS_Store 6 | /captures 7 | /Java/src/help.java 8 | /tmp 9 | 10 | -------------------------------------------------------------------------------- /Java/src/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: zhangxin 3 | * Time: 2017/4/30 0030. 4 | * Desc: 5 | */ 6 | public class Main { 7 | public static void main(String[] args) { 8 | System.out.println("please refer to the test package to make your own code. enjoy!"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Java/src/classfile/ClassReader.java: -------------------------------------------------------------------------------- 1 | package classfile; 2 | 3 | import Utils.ByteUtils; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/2 0002. 8 | * Desc: 封装的读取 class 字节码文件的 reader,里面包含一个index值,表明当前要读的字节数组的索引. 9 | */ 10 | public class ClassReader { 11 | 12 | private byte[] data; 13 | private int index = 0; 14 | 15 | public ClassReader(byte[] data) { 16 | this.data = data; 17 | } 18 | 19 | // u1 20 | public byte readUint8() { 21 | byte res = data[index++]; 22 | return res; 23 | } 24 | 25 | 26 | // u2 这里是读取一个无符号的16位整,java中没有,只能用int来代替吧; 27 | public int readUint16() { 28 | byte[] res = new byte[2]; 29 | res[0] = data[index++]; 30 | res[1] = data[index++]; 31 | return ByteUtils.bytesToU16(res); 32 | } 33 | 34 | // u4 35 | public byte[] readUint32() { 36 | byte[] res = new byte[4]; 37 | res[0] = data[index++]; 38 | res[1] = data[index++]; 39 | res[2] = data[index++]; 40 | res[3] = data[index++]; 41 | // return ByteUtils.bytesToU32(res); //如果需要转换的话,自行调用ByteUtils中的方法; 42 | return res; 43 | } 44 | 45 | public byte[] readUint64() { 46 | byte[] res = new byte[8]; 47 | res[0] = data[index++]; 48 | res[1] = data[index++]; 49 | res[2] = data[index++]; 50 | res[3] = data[index++]; 51 | res[4] = data[index++]; 52 | res[5] = data[index++]; 53 | res[6] = data[index++]; 54 | res[7] = data[index++]; 55 | return res; 56 | } 57 | 58 | /** 59 | * 读取连续的16bit长的数组,首先读出16bit,用来表示接下来要去读的多少个16bit 60 | * @return 61 | */ 62 | public int[] readUint16s() { 63 | int n = readUint16(); 64 | int[] data = new int[n]; 65 | for (int i = 0; i < n; i++) { 66 | data[i] = readUint16(); 67 | } 68 | return data; 69 | } 70 | 71 | public byte[] readBytes(int n) { 72 | byte[] res = new byte[n]; 73 | for (int i = 0; i < n; i++) { 74 | res[i] = data[index++]; 75 | } 76 | return res; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/ConstantValueAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc:ConstantValue是定长属性,只会出现在field_info结构中。 9 | * 其作用是通知JVM自动为静态变量赋值。只有被static关键字修饰的变量才有这个属性。 10 | * 对于以下三种情况: 11 | * int a1 = 123; 12 | * static int a2 = 123; 13 | * final static int a3 = 123; 14 | * 15 | * a1是实例变量,其赋值是在实例构造器方法中完成的。 16 | * 而对于a2和a3,他们都是类变量,那么其赋值有两种情况,一种是在,一种是使用ConstantValue属性; 17 | * 目前Sun Javac 的选择是:a3 使用生成 ConstantValue 属性的方法来赋值 18 | * a2则将会在中进行赋值。 19 | * 20 | * 表示常量表达式的值,其在JVM中定义如下: 21 | * ConstantValue_attribute { 22 | * u2 attribute_name_index; 23 | * u4 attribute_length; 24 | * u2 constantvalue_index; 25 | * } 26 | * 其中attribute_length的值必须是2。constantvalue_index是常量池索引,代表了常量池中一个字面量常量的引用。 27 | */ 28 | public class ConstantValueAttribute extends AttributeInfo { 29 | 30 | int constantValueIndex; 31 | @Override 32 | void readInfo(ClassReader reader) { 33 | constantValueIndex = reader.readUint16(); 34 | } 35 | 36 | public int getConstantValueIndex() { 37 | return constantValueIndex; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/DeprecatedAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc:仅起标记作用,不包含任何数据。是JDK1.1引入的,可以出现在 ClassFile、field_info和method_info结构中 9 | * 属于布尔属性,只有存在和不存在的区别。 10 | */ 11 | public class DeprecatedAttribute extends AttributeInfo { 12 | int attribute_name_index; 13 | int attribute_length; 14 | 15 | @Override 16 | void readInfo(ClassReader reader) { 17 | //由于没有数据,所以是空的. 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/ExceptionsAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: Exceptions是变长属性,记录方法抛出的异常表 9 | */ 10 | 11 | /* 12 | Exceptions_attribute { 13 | u2 attribute_name_index; 14 | u4 attribute_length; 15 | u2 number_of_exceptions; 16 | u2 exception_index_table[number_of_exceptions]; 17 | } 18 | */ 19 | 20 | public class ExceptionsAttribute extends AttributeInfo { 21 | 22 | int[] exceptionIndexTable; 23 | 24 | @Override 25 | void readInfo(ClassReader reader) { 26 | exceptionIndexTable = reader.readUint16s(); 27 | } 28 | 29 | public int[] getExceptionIndexTable() { 30 | return exceptionIndexTable; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/LineNumberTableAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: LineNumberTable属性表存放方法的行号信息,和前面介绍的SourceFile属性都属于调试信息,都不是运行时必需 9 | * 在使用javac编译器编译Java程序时,默认会在class文件中生成这些信息。可以使用javac提供的-g:none选项来关闭这些信息的生成 10 | * 描述Java源码行号与字节码行号之间的对应关系。 11 | */ 12 | public class LineNumberTableAttribute extends AttributeInfo { 13 | LineNumberTableEntry[] lineNumberTable; 14 | 15 | @Override 16 | void readInfo(ClassReader reader) { 17 | int lineNumberTableLength = reader.readUint16(); 18 | this.lineNumberTable = new LineNumberTableEntry[lineNumberTableLength]; 19 | for (int i = 0; i < lineNumberTableLength; i++) { 20 | lineNumberTable[i] = new LineNumberTableEntry(reader.readUint16(), reader.readUint16()); 21 | } 22 | } 23 | 24 | /* 根据字节码中的行号,寻找其在源代码中的行号;一般情况下;多个字节码的行号可能会对应一个源文件中的一行 25 | 0 - 15 26 | 8 - 17 27 | 14 - 21 28 | 17 - 18 29 | 18 - 20 30 | 22 - 24 31 | 可以确保的是字节码中的行号递增的,而对应的源码中的行号并不是 32 | */ 33 | public int getLineNumber(int pc) { 34 | for (int i = lineNumberTable.length - 1; i >= 0; i--) { 35 | LineNumberTableEntry entry = lineNumberTable[i]; 36 | if (pc >= entry.startPc) { 37 | return entry.lineNumber; 38 | } 39 | } 40 | return -1; 41 | } 42 | 43 | static class LineNumberTableEntry { 44 | int startPc; //字节码行号 45 | int lineNumber; //Java源码行号,二者执行的关联 46 | 47 | public LineNumberTableEntry(int startPc, int lineNumber) { 48 | this.startPc = startPc; 49 | this.lineNumber = lineNumber; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/LocalVariableTableAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: 用于描述栈帧中局部变量表中的变量和Java源码中定义的变量之间的关系。 9 | * 这并不是运行时必须的属性,但默认会生成到Class文件中,可以在Javac 中使用 -g:none 来取消这项信息; 10 | * 如果不生成这项,产生的影响是:当其他人引用这个方法时,IDE将会使用诸如arg0,arg1之类的占位符代替原来的参数名,但对运行毫无影响。 11 | * 只是在调试期间无法根据参数名从上下文中获得参数值。 12 | */ 13 | public class LocalVariableTableAttribute extends AttributeInfo { 14 | LocalVariableTableEntry[] localVariableTable; 15 | 16 | @Override 17 | void readInfo(ClassReader reader) { 18 | int localVariableTableLength = reader.readUint16(); 19 | this.localVariableTable = new LocalVariableTableEntry[localVariableTableLength]; 20 | for (int i = 0; i < localVariableTableLength; i++) { 21 | localVariableTable[i] = new LocalVariableTableEntry( 22 | reader.readUint16(), 23 | reader.readUint16(), 24 | reader.readUint16(), 25 | reader.readUint16(), 26 | reader.readUint16() 27 | ); 28 | } 29 | } 30 | 31 | static class LocalVariableTableEntry { 32 | int startPc; //代表该局部变量的生命周期开始的字节码偏移量 33 | int length; //代表该局部变量的作用范围所覆盖的长度 34 | int nameIndex; //指向常量池中个CONSTANT_Utf8_info型常量的索引,代表局部变量名称 35 | int descriptorIndex; //指向常量池中个CONSTANT_Utf8_info型常量的索引,变量描述符 36 | int index; //该局部变量在栈帧局部变量包中slot的位置 37 | 38 | public LocalVariableTableEntry(int startPc, int length, int nameIndex, int descriptorIndex, int index) { 39 | this.startPc = startPc; 40 | this.length = length; 41 | this.nameIndex = nameIndex; 42 | this.descriptorIndex = descriptorIndex; 43 | this.index = index; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/SourceFileAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | import classfile.ConstantPool; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/3 0003. 9 | * Desc:SourceFile是可选定长属性,只会出现在ClassFile结构中,用于指出源文件名 name 10 | * 这个属性也是可选的,使用 Javac -g:none 选项关闭该项信息。 11 | * 对于大多数情况,类名和文件名是一致的,但是只有在内部类中,如果抛出异常,并且没有生成该项,堆栈中将不会显示出错代码所属的文件名。 12 | */ 13 | public class SourceFileAttribute extends AttributeInfo { 14 | 15 | //sourcefile_index是常量池索引,指向CONSTANT_Utf8_info常量,其常量值是源码文件的文件名 16 | int sourceFileIndex; 17 | ConstantPool constantPool; 18 | 19 | public SourceFileAttribute(ConstantPool constantPool) { 20 | this.constantPool = constantPool; 21 | } 22 | 23 | @Override 24 | void readInfo(ClassReader reader) { 25 | sourceFileIndex = reader.readUint16(); 26 | } 27 | 28 | public String getFileName() { 29 | return constantPool.getUtf8(sourceFileIndex); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/SyntheticAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc:仅起标记作用,不包含任何数据。是JDK1.1引入的,可以出现在 ClassFile、field_info和method_info结构中 9 | * 代表词字段或方法并不是由Java源码生成的,而是由编译器自行添加的。 10 | */ 11 | public class SyntheticAttribute extends AttributeInfo { 12 | int attribute_name_index; 13 | int attribute_length; 14 | 15 | @Override 16 | void readInfo(ClassReader reader) { 17 | //由于没有数据,所以是空的. 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/classfile/attribute/UnparsedAttribute.java: -------------------------------------------------------------------------------- 1 | package classfile.attribute; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: 由于精力有限,这里不可能将所有的属性都实现,只是挑重要的几个实现,其它的都直接跳过所对应的字节数即可。 9 | */ 10 | public class UnparsedAttribute extends AttributeInfo { 11 | private String attrName; 12 | private int attrLen; 13 | private byte[] info; 14 | 15 | public UnparsedAttribute(String attrName, int attrLen) { 16 | this.attrName = attrName; 17 | this.attrLen = attrLen; 18 | } 19 | 20 | @Override 21 | void readInfo(ClassReader reader) { 22 | info = reader.readBytes(attrLen); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantClassInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | import classfile.ConstantPool; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc:表示类或者接口的符号引用 10 | * 类和超类索引,以及接口表中的接口索引指向的都是CONSTANT_Class_info常量 11 | *

12 | * ClassFileTest的this_class索引是5,其 name_index=50,super_class(Object)的索引是6,其name_index=51, 这里其实存的还是名字 13 | * 5代表的是this_class,本类类名的引用,其值在50处,可以看到常量池50的地方保存的就是jvmgo/book/ch03/ClassFileTest的字符串 14 | * 51处保存的就是java/lang/Object的字符串 15 | */ 16 | public class ConstantClassInfo extends ConstantInfo { 17 | ConstantPool constantPool; 18 | public int nameIndex; 19 | 20 | public ConstantClassInfo(ConstantPool constantPool, int i) { 21 | this.constantPool = constantPool; 22 | type = i; 23 | } 24 | 25 | 26 | @Override 27 | void readInfo(ClassReader reader) { 28 | nameIndex = reader.readUint16(); 29 | } 30 | 31 | public String getName() { 32 | return constantPool.getUtf8(nameIndex); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantDoubleInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import Utils.ByteUtils; 4 | import classfile.ClassReader; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc: 10 | */ 11 | public class ConstantDoubleInfo extends ConstantInfo { 12 | double val; 13 | 14 | public ConstantDoubleInfo(int i) { 15 | type = i; 16 | } 17 | 18 | 19 | @Override 20 | void readInfo(ClassReader reader) { 21 | byte[] data = reader.readUint64(); 22 | val = ByteUtils.byte2Double64(data); 23 | } 24 | 25 | public double getVal() { 26 | return val; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantFieldRefInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ConstantPool; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: 字段符号引用 9 | */ 10 | public class ConstantFieldRefInfo extends ConstantMemberRefInfo { 11 | public ConstantFieldRefInfo(ConstantPool constantPool,int type) { 12 | super(constantPool,type); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantFloatInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import Utils.ByteUtils; 4 | import classfile.ClassReader; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc: 10 | */ 11 | public class ConstantFloatInfo extends ConstantInfo { 12 | float val; 13 | 14 | public ConstantFloatInfo(int i) { 15 | type = i; 16 | } 17 | 18 | @Override 19 | void readInfo(ClassReader reader) { 20 | byte[] data = reader.readUint32(); 21 | val = ByteUtils.byte2Float32(data); 22 | } 23 | 24 | 25 | public float getVal() { 26 | return val; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantIntegerInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import Utils.ByteUtils; 4 | import classfile.ClassReader; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc: 使用4字节存储整数常量 10 | * 实际上比int更小的boolean、byte、short和char类型的常量也放在 CONSTANT_Integer_info 中,也是存的四字节,这是为了4k对齐,可是也造成了字节的浪费; 11 | */ 12 | public class ConstantIntegerInfo extends ConstantInfo { 13 | int val; 14 | 15 | public ConstantIntegerInfo(int i) { 16 | type = i; 17 | } 18 | 19 | @Override 20 | void readInfo(ClassReader reader) { 21 | byte[] data = reader.readUint32(); 22 | val = ByteUtils.byteToInt32(data); 23 | } 24 | 25 | 26 | 27 | public int getVal() { 28 | return val; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantInterfaceMethodRefInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ConstantPool; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: 接口方法引用消息 9 | */ 10 | public class ConstantInterfaceMethodRefInfo extends ConstantMemberRefInfo { 11 | public ConstantInterfaceMethodRefInfo(ConstantPool constantPool, int type) { 12 | super(constantPool, type); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantInvokeDynamicInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/2 0002. 8 | * Desc: 9 | */ 10 | public class ConstantInvokeDynamicInfo extends ConstantInfo { 11 | int bootstrapMethodAttrIndex; 12 | int nameAndTypeIndex; 13 | 14 | public ConstantInvokeDynamicInfo(int i) { 15 | type = i; 16 | } 17 | 18 | @Override 19 | void readInfo(ClassReader reader) { 20 | bootstrapMethodAttrIndex = reader.readUint16(); 21 | nameAndTypeIndex = reader.readUint16(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantLongInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import Utils.ByteUtils; 4 | import classfile.ClassReader; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc: 10 | */ 11 | public class ConstantLongInfo extends ConstantInfo { 12 | long val; 13 | 14 | public ConstantLongInfo(int i) { 15 | type = i; 16 | } 17 | 18 | 19 | @Override 20 | void readInfo(ClassReader reader) { 21 | byte[] data = reader.readUint64(); 22 | /* String hexData = ByteUtils.bytesToHexString(data); 23 | val = Long.parseLong(hexData, 16);*/ 24 | val = ByteUtils.byteToLong64(data); 25 | } 26 | 27 | public long getVal() { 28 | return val; 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantMemberRefInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | import classfile.ConstantPool; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc: 10 | * CONSTANT_Fieldref_info表示字段符号引用 11 | * CONSTANT_Methodref_info表示普通(非接口)方法符号引用 12 | * CONSTANT_InterfaceMethodref_info表示接口方法符号引用 13 | * 这三种类型结构一样,所以给出统一的类结构; 14 | * 然后定义三个类继承这个超类; 15 | * class_index和name_and_type_index都是常量池索引,分别指向CONSTANT_Class_info和CONSTANT_NameAndType_info常量。 16 | */ 17 | /* 18 | CONSTANT_Fieldref_info { 19 | u1 tag; 20 | u2 class_index; 21 | u2 name_and_type_index; 22 | } 23 | */ 24 | public class ConstantMemberRefInfo extends ConstantInfo { 25 | ConstantPool constantPool; 26 | int classIndex; 27 | int nameAndTypeIndex; 28 | 29 | // 该构造方法是供子类调用的,虽然有三个子类,但是并没有使用过该子类,因为当前类(父类)已经满足需求了; 30 | // public ConstantMemberRefInfo(ConstantPool constantPool) { 31 | // this.constantPool = constantPool; 32 | // } 33 | 34 | // 该构造方法是供外部调用的; 35 | public ConstantMemberRefInfo(ConstantPool constantPool, int type) { 36 | this.constantPool = constantPool; 37 | this.type = type; //因为接口,方法,字段通用这一个类,所以在构造方法中传入 i 来区分不同的类型; 38 | } 39 | 40 | 41 | @Override 42 | void readInfo(ClassReader reader) { 43 | classIndex = reader.readUint16(); 44 | nameAndTypeIndex = reader.readUint16(); 45 | } 46 | 47 | public String getClassName() { 48 | return constantPool.getClassName(classIndex); 49 | } 50 | 51 | public String[] getNameAndDescriptor() { 52 | return constantPool.getNameAndType(nameAndTypeIndex); 53 | } 54 | 55 | 56 | //下面两个方法是将上面的单独分开拿出来的, 57 | public String getName() { 58 | return constantPool.getName(nameAndTypeIndex); 59 | } 60 | 61 | public String getDescriptor() { 62 | return constantPool.getType(nameAndTypeIndex); 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantMethodHandleInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/2 0002. 8 | * Desc: ava7 中的属性,在本 JVM 中未实现 9 | */ 10 | public class ConstantMethodHandleInfo extends ConstantInfo { 11 | //关于byte上界,自行处理; 12 | private byte referenceKind; 13 | private int referenceIndex; 14 | 15 | public ConstantMethodHandleInfo(int i) { 16 | type = i; 17 | } 18 | 19 | 20 | @Override 21 | void readInfo(ClassReader reader) { 22 | referenceKind = reader.readUint8(); 23 | referenceIndex = reader.readUint16(); 24 | } 25 | 26 | public int getReferenceKind() { 27 | return (referenceKind + 256) % 256; 28 | } 29 | 30 | public int getReferenceIndex() { 31 | return referenceIndex; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantMethodRefInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ConstantPool; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/3 0003. 8 | * Desc: 方法引用消息 9 | */ 10 | public class ConstantMethodRefInfo extends ConstantMemberRefInfo { 11 | public ConstantMethodRefInfo(ConstantPool constantPool, int type) { 12 | super(constantPool, type); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantMethodTypeInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/2 0002. 8 | * Desc: Java7 中的属性,在本 JVM 中未实现 9 | */ 10 | public class ConstantMethodTypeInfo extends ConstantInfo { 11 | //关于byte上界,自行处理; 12 | private int descriptorIndex; 13 | 14 | public ConstantMethodTypeInfo(int i) { 15 | type = i; 16 | } 17 | 18 | 19 | @Override 20 | void readInfo(ClassReader reader) { 21 | descriptorIndex = reader.readUint16(); 22 | } 23 | 24 | public int getDescriptorIndex() { 25 | return descriptorIndex; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantNameAndTypeInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/2 0002. 8 | * Desc: 9 | * name_index和descriptor_index都是常量池索引,指向CONSTANT_Utf8_info常量。 10 | * 字段(成员变量)和方法名就是代码中出现的(或者编译器生成的)字段或方法的名字。 11 | * 字段或方法名由name_index给出,对应的就是代码中真实的成员变量名或者方法名 12 | * 字段或方法的描述符由descriptor_index给出 13 | * 描述符:描述字段的类型,描述方法的参数类型; 14 | *

15 | * (1) 16 | * a:基本类型byte、short、char、int、long、float和double的描述符是单个字母,分别对应B、S、C、I、J、F和D。注意,long的描述符是J而不是L。 17 | * b:引用类型的描述符是 L + 类的完全限定名 + 分号 eg: Ljava.lang.String; 18 | * c:数组类型的描述符是[+数组元素类型描述符。eg: [I 代表int[] 19 | *

20 | * (2)字段描述符就是字段类型的描述符。 21 | * (3)方法描述符是(分号分隔的参数类型描述符)+返回值类型描述符,其中void返回值由单个字母V表示。eg:(Ljava.lang.String;I)Ljava.lang.String 22 | * 代表的就是 String (String int),方法名由name_index给出; 23 | */ 24 | 25 | /* 26 | CONSTANT_NameAndType_info { 27 | u1 tag; 28 | u2 name_index; 29 | u2 descriptor_index; 30 | } 31 | */ 32 | public class ConstantNameAndTypeInfo extends ConstantInfo { 33 | public int nameIndex; 34 | public int descriptorIndex; 35 | 36 | public ConstantNameAndTypeInfo(int i) { 37 | type = i; 38 | } 39 | 40 | 41 | @Override 42 | void readInfo(ClassReader reader) { 43 | nameIndex = reader.readUint16(); 44 | descriptorIndex = reader.readUint16(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Java/src/classfile/classconstant/ConstantStringInfo.java: -------------------------------------------------------------------------------- 1 | package classfile.classconstant; 2 | 3 | import classfile.ClassReader; 4 | import classfile.ConstantPool; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/2 0002. 9 | * Desc:本身并不存放字符串数据,只存了常量池索引,这个索引指向一个CONSTANT_Utf8_info常量 10 | * 所以在readInfo中首先读出索引,然后在去对应的CONSTANT_Utf8_info常量中读取具体的字符串 11 | */ 12 | public class ConstantStringInfo extends ConstantInfo { 13 | ConstantPool constantPool; 14 | int stringIndex; 15 | 16 | public ConstantStringInfo(ConstantPool constantPool,int i) { 17 | this.constantPool = constantPool; 18 | type = i; 19 | } 20 | 21 | 22 | //读取常量池索引 23 | @Override 24 | void readInfo(ClassReader reader) { 25 | stringIndex = reader.readUint16(); 26 | } 27 | 28 | public String getString() { 29 | return constantPool.getUtf8(stringIndex); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Java/src/classpath/CompositeEntry.java: -------------------------------------------------------------------------------- 1 | package classpath; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/4/30 0030. 9 | * Desc: CompositeEntry由众多的Entry组成,正好可以表示成 Entry list; 10 | * 构造函数把参数(路径列表)按分隔符分成小路径,然后把每个小路径都转换成具体的 Entry实例 11 | */ 12 | public class CompositeEntry extends Entry { 13 | //不用担心,list中的entry是按照父类来转入的,在真正执行的时候,是按照各自的实际类型执行readClass()方法 14 | ArrayList compositeEntries; 15 | private String pathList; 16 | 17 | public CompositeEntry() { 18 | } 19 | 20 | public CompositeEntry(String pathList, String pathListSeparator) { 21 | this.pathList = pathList; 22 | String[] paths = pathList.split(pathListSeparator); 23 | compositeEntries = new ArrayList(paths.length); 24 | for (int i = 0; i < paths.length; i++) { 25 | compositeEntries.add(new DirEntry(paths[i])); 26 | } 27 | } 28 | 29 | @Override 30 | byte[] readClass(String className) { 31 | byte[] data; 32 | for (int i = 0; i < compositeEntries.size(); i++) { 33 | try { 34 | data = compositeEntries.get(i).readClass(className); 35 | if (data != null) { 36 | return data; 37 | } 38 | } catch (IOException e) { 39 | e.printStackTrace(); 40 | } 41 | 42 | } 43 | return null; 44 | } 45 | 46 | @Override 47 | String printClassName() { 48 | return pathList; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Java/src/classpath/Entry.java: -------------------------------------------------------------------------------- 1 | package classpath; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/4/30 0030. 9 | * Desc: 10 | */ 11 | public abstract class Entry { 12 | //路径分隔符,在window下,使用 ; 分割开的 在Unix/Linux下使用: 分割开的 13 | public static final String pathListSeparator = System.getProperty("os.name").contains("Windows") ? ";" : ":"; 14 | 15 | /** 16 | * 负责寻找和加载class文件 17 | * 18 | * @param className class文件的相对路径,路径之间用斜线 / 分隔,文件名有.class后缀 19 | */ 20 | abstract byte[] readClass(String className) throws IOException; 21 | 22 | /** 23 | * @return 返回className的字符串表示形式; 24 | */ 25 | abstract String printClassName(); 26 | 27 | 28 | /** 29 | * 工厂方法,根据传入的path的形式不同, 30 | * 31 | * @param path 命令行得到的路径字符串 32 | * @return 创建具体的Entry 33 | */ 34 | static Entry createEntry(String path) { 35 | if (path != null) { 36 | if (path.contains(pathListSeparator)) { 37 | return new CompositeEntry(path, pathListSeparator); 38 | } else if (path.contains("*")) { 39 | return new WildcardEntry(""); 40 | } else if (path.contains(".jar") || path.contains(".JAR") || path.contains(".zip") 41 | || path.contains("" + ".ZIP")) { 42 | return new ZipJarEntry(path); 43 | } 44 | return new DirEntry(path); 45 | } else { 46 | //如果命令行中没有显式的指定-cp选项,那么默认要找的class就在当前路径下 47 | File file = new File(""); 48 | try { 49 | path = file.getCanonicalPath(); 50 | return new DirEntry(path); 51 | } catch (IOException e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | throw new RuntimeException("illegal classpath format,or you should point out the classpath explicitly"); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Java/src/classpath/WildcardEntry.java: -------------------------------------------------------------------------------- 1 | package classpath; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/4/30 0030. 9 | * Desc:处理的是路径匹配的 xxx.* 的情况 10 | * 首先把路径末尾的星号去掉,得到baseDir,然后遍历该baseDir路径下的文件,只取以 .jar 结尾的文件; 11 | * 12 | * 这个类其实是CompositeEntry的一个包装类; 13 | */ 14 | public class WildcardEntry extends Entry { 15 | 16 | public CompositeEntry compositeEntry; 17 | 18 | public WildcardEntry(String jreLibPath) { 19 | 20 | String baseDir = jreLibPath.substring(0, jreLibPath.length() - 1); //去掉最后的一个字符 * 21 | File dir = new File(baseDir); 22 | File[] files = dir.listFiles(); 23 | compositeEntry = new CompositeEntry(); 24 | compositeEntry.compositeEntries = new ArrayList(); 25 | for (File file : files) { 26 | if (file.isFile() && file.getName().endsWith(".jar")) { 27 | compositeEntry.compositeEntries.add(new ZipJarEntry(baseDir,file.getName())); 28 | } 29 | } 30 | // System.out.println(compositeEntry.compositeEntries.size()); 31 | } 32 | 33 | @Override 34 | byte[] readClass(String className) { 35 | return compositeEntry.readClass(className); 36 | } 37 | 38 | @Override 39 | String printClassName() { 40 | return null; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Java/src/instructions/base/BranchInstruction.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/5 0005. 6 | * Desc:表示跳转指令,Offset字段存放跳转偏移量。 7 | * 这个类是指令的子类,只负责读取offset,和BranchLogic类区别是: 8 | * BranchLogic负责将BranchInstruction拿到的offset值,从新计算pc,并赋值给Frame.pc; 9 | */ 10 | public abstract class BranchInstruction implements Instruction { 11 | public int offset; 12 | 13 | @Override 14 | public void fetchOperands(BytecodeReader reader) { 15 | offset = reader.readInt16(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/base/BranchLogic.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | import runtimedata.Zframe; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/5 0005. 8 | * Desc: 真正的跳转逻辑,因为这个函数在很多指令中都会用到,所以把它定义base中 9 | */ 10 | public class BranchLogic { 11 | public static void branch(Zframe frame, int offset) { 12 | int pc = frame.getThread().getPc(); 13 | int nextPC = pc + offset; 14 | frame.setNextPC(nextPC); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/base/BytecodeReader.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | import Utils.ByteUtils; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/5 0005. 8 | * Desc: 9 | */ 10 | public class BytecodeReader { 11 | private byte[] code; //byte的范围四-128~127,和go中的byte:0~255不同,所以在取数据的时候需要注意; 12 | private int pc; 13 | 14 | /** 15 | * @param code 16 | * @param pc 17 | */ 18 | public void reset(byte[] code, int pc) { 19 | this.code = code; 20 | this.pc = pc; 21 | } 22 | 23 | public int getPc() { 24 | return pc; 25 | } 26 | 27 | public byte readInt8() { 28 | byte res = code[pc]; 29 | pc++; 30 | return res; 31 | } 32 | 33 | public int readUint8() { 34 | int res = code[pc]; 35 | res = (res + 256) % 256; 36 | pc++; 37 | return res; 38 | } 39 | 40 | 41 | public int readInt16() { 42 | return (short) readUint16(); 43 | } 44 | 45 | public int readUint16() { 46 | int a1 = readUint8(); 47 | int a2 = readUint8(); 48 | return (a1 << 8 | a2); 49 | } 50 | 51 | public int readInt32() { 52 | byte[] data = new byte[4]; 53 | data[0] = readInt8(); 54 | data[1] = readInt8(); 55 | data[2] = readInt8(); 56 | data[3] = readInt8(); 57 | 58 | return ByteUtils.byteToInt32(data); 59 | } 60 | 61 | public int[] readInt32s(int n) { 62 | int[] data = new int[n]; 63 | for (int i = 0; i < n; i++) { 64 | data[i] = readInt32(); 65 | } 66 | return data; 67 | } 68 | 69 | 70 | //4k对齐,没有对齐的会有填充数据,这些数据要忽略掉; 71 | public void skipPadding() { 72 | while (pc % 4 != 0) { 73 | readInt8(); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Java/src/instructions/base/ClassInitLogic.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | import runtimedata.Zframe; 4 | import runtimedata.Zthread; 5 | import runtimedata.heap.Zclass; 6 | import runtimedata.heap.Zmethod; 7 | 8 | /** 9 | * @author zachaxy 10 | * @date 17/12/28 11 | * desc:执行类的初始化 12 | */ 13 | public class ClassInitLogic { 14 | public static void initClass(Zthread thread, Zclass clazz) { 15 | clazz.startInit(); 16 | scheduleClinit(thread, clazz); 17 | initSuperClass(thread, clazz); 18 | } 19 | 20 | private static void scheduleClinit(Zthread thread, Zclass clazz) { 21 | Zmethod clinit = clazz.getMethod("", "()V"); 22 | if (clinit != null && clinit.getClazz() == clazz) { 23 | // exec 24 | Zframe newFrame = thread.createFrame(clinit); 25 | thread.pushFrame(newFrame); 26 | } 27 | } 28 | 29 | private static void initSuperClass(Zthread thread, Zclass clazz) { 30 | if (!clazz.isInterface()) { 31 | Zclass superClass = clazz.getSuperClass(); 32 | if (superClass != null && !superClass.isInitStarted()) { 33 | initClass(thread, superClass); 34 | } 35 | } 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /Java/src/instructions/base/Index16Instruction.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/5 0005. 6 | * Desc:有一些指令需要访问运行时常量池,常量池索引由两字节操作数给出。 7 | */ 8 | public abstract class Index16Instruction implements Instruction { 9 | public int index; 10 | 11 | @Override 12 | public void fetchOperands(BytecodeReader reader) { 13 | index = reader.readUint16(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Java/src/instructions/base/Index8Instruction.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/5 0005. 6 | * Desc:存储和加载类指令需要根据索引存取局部变量表,索引由单字节操作数给出 7 | * 部分存储和加载指令是自带操作数的,所以不需要index; 8 | * 然后其余部分的指令,只有加载/存储的语义,并不知道将数据存储/加载到局部变量表的哪一位,所以需要index 9 | */ 10 | public abstract class Index8Instruction implements Instruction { 11 | 12 | public Index8Instruction(){} 13 | 14 | public int index; 15 | 16 | @Override 17 | public void fetchOperands(BytecodeReader reader) { 18 | index = reader.readUint8(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/base/Instruction.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | import runtimedata.Zframe; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/5 0005. 8 | * Desc: 每个指令都会实现该接口,所有的指令逻辑都是先从字节码数组中取数据,然后执行各自的逻辑 9 | */ 10 | public interface Instruction { 11 | //从字节码中提取操作数 12 | void fetchOperands(BytecodeReader reader); 13 | 14 | //执行指令逻辑 15 | void execute(Zframe frame); 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/base/MethodInvokeLogic.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | import runtimedata.Slot; 4 | import runtimedata.Zframe; 5 | import runtimedata.Zthread; 6 | import runtimedata.heap.Zmethod; 7 | 8 | /** 9 | * @author zachaxy 10 | * @date 17/12/27 11 | */ 12 | public class MethodInvokeLogic { 13 | 14 | public static void invokeMethod(Zframe invokerFrame, Zmethod method) { 15 | Zthread thread = invokerFrame.getThread(); 16 | Zframe newFrame = thread.createFrame(method); 17 | thread.pushFrame(newFrame); 18 | 19 | int argSlotCount = method.getArgSlotCount(); 20 | if (argSlotCount > 0) { 21 | for (int i = argSlotCount - 1; i >= 0; i--) { 22 | Slot slot = invokerFrame.getOperandStack().popSlot(); 23 | newFrame.getLocalVars().setSlot(i, slot); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/instructions/base/NoOperandsInstruction.java: -------------------------------------------------------------------------------- 1 | package instructions.base; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/5 0005. 6 | * Desc:表示没有操作数的指令,所以没有定义 任何字段。FetchOperands方法也是空实现,什么也不用读 7 | */ 8 | public abstract class NoOperandsInstruction implements Instruction{ 9 | 10 | @Override 11 | public void fetchOperands(BytecodeReader reader) { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/dcmp/DCMP.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.dcmp; 2 | 3 | import runtimedata.OperandStack; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 由于浮点数计算有可能产生NaN(Not a Number)值,所以比较两个浮点数时,除了大于、等于、小于之外, 还有第4种结果:无法比较 10 | * fcmpg和fcmpl指令的区别就在于对第4种结果的定义; 11 | * 当两个float变量中至少有一个是NaN时,用fcmpg指令比较的结果是1,而用fcmpl指令比较的结果是-1。 12 | */ 13 | public class DCMP { 14 | static void _dcmp(Zframe frame, boolean flag) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val2 = stack.popDouble(); 17 | double val1 = stack.popDouble(); 18 | 19 | if (val1 > val2) { 20 | stack.pushInt(1); 21 | } else if (val1 == val2) { 22 | stack.pushInt(0); 23 | } else if (val1 > val2) { 24 | stack.pushInt(-1); 25 | } else if (flag) { 26 | stack.pushInt(1); 27 | } else { 28 | stack.pushInt(-1); 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/dcmp/DCMPG.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.dcmp; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.comparisons.fcmp.FCMP; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DCMPG extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | DCMP._dcmp(frame, true); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/dcmp/DCMPL.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.dcmp; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 10 | */ 11 | public class DCMPL extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | DCMP._dcmp(frame, false); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/fcmp/FCMP.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.fcmp; 2 | 3 | import runtimedata.OperandStack; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 由于浮点数计算有可能产生NaN(Not a Number)值,所以比较两个浮点数时,除了大于、等于、小于之外, 还有第4种结果:无法比较 10 | * fcmpg和fcmpl指令的区别就在于对第4种结果的定义; 11 | * 当两个float变量中至少有一个是NaN时,用fcmpg指令比较的结果是1,而用fcmpl指令比较的结果是-1。 12 | */ 13 | public class FCMP { 14 | static void _fcmp(Zframe frame, boolean flag) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val2 = stack.popFloat(); 17 | float val1 = stack.popFloat(); 18 | 19 | if (val1 > val2) { 20 | stack.pushInt(1); 21 | } else if (val1 == val2) { 22 | stack.pushInt(0); 23 | } else if (val1 > val2) { 24 | stack.pushInt(-1); 25 | } else if (flag) { 26 | stack.pushInt(1); 27 | } else { 28 | stack.pushInt(-1); 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/fcmp/FCMPG.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.fcmp; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 10 | */ 11 | public class FCMPG extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | FCMP._fcmp(frame, true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/fcmp/FCMPL.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.fcmp; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 10 | */ 11 | public class FCMPL extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | FCMP._fcmp(frame, false); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifacmp/IF_ACMPEQ.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifacmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IF_ACMPEQ extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | if (IfAcmp._acmp(frame)) { 16 | BranchLogic.branch(frame, offset); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifacmp/IF_ACMPNE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifacmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IF_ACMPNE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | if (!IfAcmp._acmp(frame)) { 16 | BranchLogic.branch(frame, offset); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifacmp/IfAcmp.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifacmp; 2 | 3 | import runtimedata.OperandStack; 4 | import runtimedata.Zframe; 5 | import runtimedata.heap.Zobject; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IfAcmp { 13 | public static boolean _acmp(Zframe frame) { 14 | OperandStack stack = frame.getOperandStack(); 15 | Zobject ref2 = stack.popRef(); 16 | Zobject ref1 = stack.popRef(); 17 | return ref1 == ref2; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifcond/IFEQ.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifcond; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IFEQ extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int val = frame.getOperandStack().popInt(); 16 | if (val == 0) { 17 | BranchLogic.branch(frame, offset); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifcond/IFGE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifcond; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IFGE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int val = frame.getOperandStack().popInt(); 16 | if (val >= 0) { 17 | BranchLogic.branch(frame, offset); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifcond/IFGT.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifcond; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IFGT extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int val = frame.getOperandStack().popInt(); 16 | if (val > 0) { 17 | BranchLogic.branch(frame, offset); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifcond/IFLE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifcond; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IFLE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int val = frame.getOperandStack().popInt(); 16 | if (val <= 0) { 17 | BranchLogic.branch(frame, offset); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifcond/IFLT.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifcond; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IFLT extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int val = frame.getOperandStack().popInt(); 16 | if (val < 0) { 17 | BranchLogic.branch(frame, offset); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ifcond/IFNE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ifcond; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IFNE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int val = frame.getOperandStack().popInt(); 16 | if (val != 0) { 17 | BranchLogic.branch(frame, offset); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IF_ICMPEQ.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/6 0006. 10 | * Desc: 11 | */ 12 | public class IF_ICMPEQ extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int[] res = IfIcmp._icmpPop(frame); 16 | int val1 = res[0]; 17 | int val2 = res[1]; 18 | if (val1 == val2) { 19 | BranchLogic.branch(frame, offset); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IF_ICMPGE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/6 0006. 10 | * Desc: 11 | */ 12 | public class IF_ICMPGE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int[] res = IfIcmp._icmpPop(frame); 16 | int val1 = res[0]; 17 | int val2 = res[1]; 18 | if (val1 >= val2) { 19 | BranchLogic.branch(frame, offset); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IF_ICMPGT.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/6 0006. 10 | * Desc: 11 | */ 12 | public class IF_ICMPGT extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int[] res = IfIcmp._icmpPop(frame); 16 | int val1 = res[0]; 17 | int val2 = res[1]; 18 | if (val1 > val2) { 19 | BranchLogic.branch(frame, offset); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IF_ICMPLE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/6 0006. 10 | * Desc: 11 | */ 12 | public class IF_ICMPLE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int[] res = IfIcmp._icmpPop(frame); 16 | int val1 = res[0]; 17 | int val2 = res[1]; 18 | if (val1 <= val2) { 19 | BranchLogic.branch(frame, offset); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IF_ICMPLT.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/6 0006. 10 | * Desc: 11 | */ 12 | public class IF_ICMPLT extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int[] res = IfIcmp._icmpPop(frame); 16 | int val1 = res[0]; 17 | int val2 = res[1]; 18 | if (val1 < val2) { 19 | BranchLogic.branch(frame, offset); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IF_ICMPNE.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/6 0006. 10 | * Desc: 11 | */ 12 | public class IF_ICMPNE extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | int[] res = IfIcmp._icmpPop(frame); 16 | int val1 = res[0]; 17 | int val2 = res[1]; 18 | if (val1 != val2) { 19 | BranchLogic.branch(frame, offset); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/ificmp/IfIcmp.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.ificmp; 2 | 3 | import runtimedata.OperandStack; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/6 0006. 9 | * Desc: 10 | */ 11 | public class IfIcmp { 12 | static int[] _icmpPop(Zframe frame) { 13 | OperandStack stack = frame.getOperandStack(); 14 | int[] res = new int[2]; 15 | res[1] = stack.popInt(); 16 | res[0] = stack.popInt(); 17 | return res; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/comparisons/lcmp/LCMP.java: -------------------------------------------------------------------------------- 1 | package instructions.comparisons.lcmp; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LCMP extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | long val1 = stack.popLong(); 18 | if (val1 > val2) { 19 | stack.pushInt(1); 20 | } else if (val1 == val2) { 21 | stack.pushInt(0); 22 | } else { 23 | stack.pushInt(-1); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ACONST_NULL.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: push null 10 | */ 11 | public class ACONST_NULL extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushRef(null); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/BIPUSH.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.BytecodeReader; 4 | import instructions.base.Instruction; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc:bipush指令从操作数中获取一个byte型整数,扩展成int型,然后推入栈顶 11 | */ 12 | public class BIPUSH implements Instruction { 13 | int val; 14 | 15 | @Override 16 | public void fetchOperands(BytecodeReader reader) { 17 | val = reader.readInt8(); 18 | } 19 | 20 | @Override 21 | public void execute(Zframe frame) { 22 | // 源码是独到一个int8,然后再用int32将其扩展,那么就变成了实际值。但是在Java中直接扩展还是原值,所以要进行修正在push; 23 | frame.getOperandStack().pushInt((val + 256) % 256); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/DCONST_0.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc:Push double 10 | */ 11 | public class DCONST_0 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushDouble(0.0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/DCONST_1.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 10 | */ 11 | public class DCONST_1 extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | frame.getOperandStack().pushDouble(1.0); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/FCONST_0.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push float 10 | */ 11 | public class FCONST_0 extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | frame.getOperandStack().pushFloat(0.0f); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/FCONST_1.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push float 10 | */ 11 | public class FCONST_1 extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | frame.getOperandStack().pushFloat(1.0f); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/FCONST_2.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push float 10 | */ 11 | public class FCONST_2 extends NoOperandsInstruction { 12 | @Override 13 | public void execute(Zframe frame) { 14 | frame.getOperandStack().pushFloat(2.0f); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_0.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_0 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_1.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_1 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_2.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_2 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_3.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_3 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_4.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_4 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(4); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_5.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_5 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(5); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/ICONST_M1.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class ICONST_M1 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushInt(-1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/LCONST_0.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class LCONST_0 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushLong(0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/LCONST_1.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: Push int constant 10 | */ 11 | public class LCONST_1 extends NoOperandsInstruction { 12 | 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().pushLong(1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/LDC.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import classfile.classconstant.ConstantInfo; 4 | import instructions.base.Index8Instruction; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.*; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/26 12 | * desc:获取操作数index,通过 index 来获取运行时常量池中的常量,并将其压入操作数栈 13 | */ 14 | public class LDC extends Index8Instruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | Zclass clazz = frame.getMethod().getClazz(); 19 | RuntimeConstantInfo runtimeConstant = clazz.getRuntimeConstantPool().getRuntimeConstant(index); 20 | switch (runtimeConstant.getType()) { 21 | case ConstantInfo.CONSTANT_Integer: 22 | operandStack.pushInt((Integer) runtimeConstant.getValue()); 23 | break; 24 | case ConstantInfo.CONSTANT_Float: 25 | operandStack.pushFloat((Float) runtimeConstant.getValue()); 26 | break; 27 | case ConstantInfo.CONSTANT_String: 28 | Zobject internedStr = StringPool.jString(clazz.getLoader(), (String) runtimeConstant.getValue()); 29 | operandStack.pushRef(internedStr); 30 | break; 31 | case ConstantInfo.CONSTANT_Class: 32 | ClassRef classRef = (ClassRef) runtimeConstant.getValue(); 33 | Zobject jObject = classRef.resolvedClass().getjObject(); 34 | operandStack.pushRef(jObject); 35 | break; 36 | // case MethodType, MethodHandle //Java7中的特性,不在本虚拟机范围内 37 | default: 38 | break; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/LDC2_W.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import classfile.classconstant.ConstantInfo; 4 | import instructions.base.Index16Instruction; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.RuntimeConstantInfo; 8 | import runtimedata.heap.Zclass; 9 | 10 | /** 11 | * @author zachaxy 12 | * @date 17/12/26 13 | * desc:LDC2_W 和 LDC 的区别是,其获取常量池的常量类型为 Long 和 Double,都是 16bit 宽的 14 | */ 15 | public class LDC2_W extends Index16Instruction { 16 | @Override 17 | public void execute(Zframe frame) { 18 | OperandStack operandStack = frame.getOperandStack(); 19 | Zclass clazz = frame.getMethod().getClazz(); 20 | RuntimeConstantInfo runtimeConstant = clazz.getRuntimeConstantPool().getRuntimeConstant(index); 21 | switch (runtimeConstant.getType()){ 22 | case ConstantInfo.CONSTANT_Long: 23 | operandStack.pushLong((Long) runtimeConstant.getValue()); 24 | break; 25 | case ConstantInfo.CONSTANT_Double: 26 | operandStack.pushDouble((Double) runtimeConstant.getValue()); 27 | break; 28 | default: 29 | throw new ClassFormatError(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/LDC_W.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.BytecodeReader; 4 | 5 | /** 6 | * @author zachaxy 7 | * @date 17/12/26 8 | * desc:LDC_W和 LDC 的 execute 是完全一样的,唯一的区别就是去操作数的位宽,w 取16位,非 w 取8位 9 | * 所以 LDC_W 复用了 LDC 的 execute 过程,但是重写了其 fetch 方法,改为取16位宽 10 | */ 11 | public class LDC_W extends LDC { 12 | @Override 13 | public void fetchOperands(BytecodeReader reader) { 14 | index = reader.readUint16(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/NOP.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: nop指令是最简单的一条指令,因为它什么也不做 10 | */ 11 | public class NOP extends NoOperandsInstruction{ 12 | @Override 13 | public void execute(Zframe frame) { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Java/src/instructions/constants/SIPUSH.java: -------------------------------------------------------------------------------- 1 | package instructions.constants; 2 | 3 | import instructions.base.BytecodeReader; 4 | import instructions.base.Instruction; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc:sipush指令从操作数中获取一个short型整数,扩展成int型,然后推入栈顶 11 | */ 12 | public class SIPUSH implements Instruction { 13 | int val; 14 | 15 | @Override 16 | public void fetchOperands(BytecodeReader reader) { 17 | val = reader.readInt16(); 18 | } 19 | 20 | @Override 21 | public void execute(Zframe frame) { 22 | frame.getOperandStack().pushInt((val + 65536) % 65536); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Java/src/instructions/control/ARETURN.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | import runtimedata.Zthread; 6 | import runtimedata.heap.Zobject; 7 | 8 | /** 9 | * @author zachaxy 10 | * @date 17/12/27 11 | * desc:返回值为 实例对象 的 return 指令 12 | */ 13 | public class ARETURN extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | Zthread thread = frame.getThread(); 17 | Zframe currentFrame = thread.popFrame(); 18 | Zframe invokerFrame = thread.getCurrentFrame(); 19 | Zobject val = currentFrame.getOperandStack().popRef(); 20 | invokerFrame.getOperandStack().pushRef(val); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Java/src/instructions/control/DRETURN.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | import runtimedata.Zthread; 6 | 7 | /** 8 | * @author zachaxy 9 | * @date 17/12/27 10 | * desc:返回值为 double 的 return 指令 11 | */ 12 | public class DRETURN extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Zthread thread = frame.getThread(); 16 | Zframe currentFrame = thread.popFrame(); 17 | Zframe invokerFrame = thread.getCurrentFrame(); 18 | double val = currentFrame.getOperandStack().popDouble(); 19 | invokerFrame.getOperandStack().pushDouble(val); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/control/FRETURN.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | import runtimedata.Zthread; 6 | 7 | /** 8 | * @author zachaxy 9 | * @date 17/12/27 10 | * desc:返回值为 float 的 return 指令 11 | */ 12 | public class FRETURN extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Zthread thread = frame.getThread(); 16 | Zframe currentFrame = thread.popFrame(); 17 | Zframe invokerFrame = thread.getCurrentFrame(); 18 | float val = currentFrame.getOperandStack().popFloat(); 19 | invokerFrame.getOperandStack().pushFloat(val); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/control/GOTO.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class GOTO extends BranchInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | BranchLogic.branch(frame,offset); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/control/IRETURN.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | import runtimedata.Zthread; 6 | 7 | /** 8 | * @author zachaxy 9 | * @date 17/12/27 10 | * desc:返回值为 int 的 return 指令 11 | * 执行方法在执行结束后,如果有返回值,其返回值会放在该方法的操作数栈 12 | * 执行方法的外部——调用方法,需要将执行方法的返回值,压入调用方法的操作数栈 13 | */ 14 | public class IRETURN extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | Zthread thread = frame.getThread(); 18 | Zframe currentFrame = thread.popFrame(); 19 | Zframe invokerFrame = thread.getCurrentFrame(); 20 | int val = currentFrame.getOperandStack().popInt(); 21 | invokerFrame.getOperandStack().pushInt(val); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Java/src/instructions/control/LOOKUP_SWITCH.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.BranchLogic; 4 | import instructions.base.BytecodeReader; 5 | import instructions.base.Instruction; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc:如果case值不可以编码成一个索引表(case中的数值不是连续的),则实现成lookupswitch指令 12 | */ 13 | public class LOOKUP_SWITCH implements Instruction { 14 | int defaultOffset; 15 | int npairs; 16 | //matchOffsets有点像Map,它的key是case值,value是跳转偏移,但是并没有实现成map,而是用数组代替,两个连续的数位key-value; 17 | int[] matchOffsets; 18 | 19 | @Override 20 | public void fetchOperands(BytecodeReader reader) { 21 | reader.skipPadding(); 22 | defaultOffset = reader.readInt32(); 23 | npairs = reader.readInt32(); 24 | matchOffsets = reader.readInt32s(npairs * 2); 25 | } 26 | 27 | @Override 28 | public void execute(Zframe frame) { 29 | int key = frame.getOperandStack().popInt(); 30 | for (int i = 0; i < npairs * 2; i += 2) { 31 | if (matchOffsets[i] == key) { 32 | int offset = matchOffsets[i + 1]; 33 | BranchLogic.branch(frame, defaultOffset); 34 | return; 35 | } 36 | } 37 | BranchLogic.branch(frame, defaultOffset); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Java/src/instructions/control/LRETURN.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | import runtimedata.Zthread; 6 | 7 | /** 8 | * @author zachaxy 9 | * @date 17/12/27 10 | * desc:返回值为 long 的 return 指令 11 | */ 12 | public class LRETURN extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Zthread thread = frame.getThread(); 16 | Zframe currentFrame = thread.popFrame(); 17 | Zframe invokerFrame = thread.getCurrentFrame(); 18 | long val = currentFrame.getOperandStack().popLong(); 19 | invokerFrame.getOperandStack().pushLong(val); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/control/RETURN.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * @author zachaxy 8 | * @date 17/12/27 9 | * return 指令;没有具体的返回值,用在 void 类型的方法中,这种方法即使不在 Java 代码中写 return 语句 10 | * 编译器也会自动在方法的结尾添加一条 return 指令; 11 | */ 12 | public class RETURN extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getThread().popFrame(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/control/TABLE_SWITCH.java: -------------------------------------------------------------------------------- 1 | package instructions.control; 2 | 3 | import instructions.base.BranchLogic; 4 | import instructions.base.BytecodeReader; 5 | import instructions.base.Instruction; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: 如果case值可以编码成一个索引表(case中的数值是连续的),则实现成tableswitch指令 12 | */ 13 | public class TABLE_SWITCH implements Instruction { 14 | int defaultOffset; 15 | //low和high记录case的取值范围 16 | int low; 17 | int high; 18 | //jumpOffsets是一个索引表,里面存放high-low+1个int值,,对应各种case情况下,执行跳转所需的字节码偏移量 19 | int[] jumpOffsets; 20 | 21 | @Override 22 | public void fetchOperands(BytecodeReader reader) { 23 | //tableswitch指令操作码的后面有0~3字节的padding,以保证 defaultOffset在字节码中的地址是4的倍数 24 | reader.skipPadding(); 25 | defaultOffset = reader.readInt32(); 26 | low = reader.readInt32(); 27 | high = reader.readInt32(); 28 | int jumpOffsetsCount = high - low + 1; 29 | jumpOffsets = reader.readInt32s(jumpOffsetsCount); 30 | } 31 | 32 | @Override 33 | public void execute(Zframe frame) { 34 | int index = frame.getOperandStack().popInt(); 35 | int offset; 36 | if ((index >= low) && (index <= high)) { 37 | offset = jumpOffsets[index - low]; 38 | } else { 39 | offset = defaultOffset; 40 | } 41 | 42 | BranchLogic.branch(frame, offset); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/d2x/D2F.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.d2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class D2F extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val1 = stack.popDouble(); 17 | float val2 = (float) val1; 18 | stack.pushFloat(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/d2x/D2I.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.d2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class D2I extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val1 = stack.popDouble(); 17 | int val2 = (int) val1; 18 | stack.pushInt(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/d2x/D2L.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.d2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class D2L extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val1 = stack.popDouble(); 17 | long val2 = (long) val1; 18 | stack.pushLong(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/f2x/F2D.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.f2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class F2D extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val1 = stack.popFloat(); 17 | double val2 = val1; 18 | stack.pushDouble(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/f2x/F2I.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.f2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class F2I extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val1 = stack.popFloat(); 17 | int val2 = (int) val1; 18 | stack.pushInt(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/f2x/F2L.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.f2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class F2L extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val1 = stack.popFloat(); 17 | long val2 = (long) val1; 18 | stack.pushLong(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/i2x/I2B.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.i2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class I2B extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | byte val2 = (byte) val1; 18 | stack.pushInt(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/i2x/I2C.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.i2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class I2C extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | char val2 = (char) val1; 18 | stack.pushInt(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/i2x/I2D.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.i2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class I2D extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | double val2 = (double) val1; 18 | stack.pushDouble(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/i2x/I2F.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.i2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class I2F extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | float val2 = (float) val1; 18 | stack.pushFloat(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/i2x/I2L.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.i2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class I2L extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | long val2 = (long) val1; 18 | stack.pushLong(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/i2x/I2S.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.i2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class I2S extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | short val2 = (short) val1; 18 | stack.pushInt(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/l2x/L2D.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.l2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class L2D extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val1 = stack.popLong(); 17 | double val2 = (double) val1; 18 | stack.pushDouble(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/l2x/L2F.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.l2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class L2F extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val1 = stack.popLong(); 17 | float val2 = (float) val1; 18 | stack.pushFloat(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/conversions/l2x/L2I.java: -------------------------------------------------------------------------------- 1 | package instructions.conversions.l2x; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class L2I extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val1 = stack.popLong(); 17 | int val2 = (int) val1; 18 | stack.pushInt(val2); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Java/src/instructions/extended/GOTO_W.java: -------------------------------------------------------------------------------- 1 | package instructions.extended; 2 | 3 | import instructions.base.BranchLogic; 4 | import instructions.base.BytecodeReader; 5 | import instructions.base.Instruction; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/6 0006. 11 | * Desc: goto_w指令和goto指令的唯一区别就是索引从2字节变成了4字节 12 | */ 13 | public class GOTO_W implements Instruction { 14 | int offset; 15 | 16 | @Override 17 | public void fetchOperands(BytecodeReader reader) { 18 | offset = reader.readInt32(); 19 | } 20 | 21 | @Override 22 | public void execute(Zframe frame) { 23 | BranchLogic.branch(frame, offset); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Java/src/instructions/extended/IFNONNULL.java: -------------------------------------------------------------------------------- 1 | package instructions.extended; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.Zobject; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/6 0006. 11 | * Desc: 12 | */ 13 | public class IFNONNULL extends BranchInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | Zobject ref = frame.getOperandStack().popRef(); 17 | if (ref != null) { 18 | BranchLogic.branch(frame, offset); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/extended/IFNULL.java: -------------------------------------------------------------------------------- 1 | package instructions.extended; 2 | 3 | import instructions.base.BranchInstruction; 4 | import instructions.base.BranchLogic; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.Zobject; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/6 0006. 11 | * Desc: 12 | */ 13 | public class IFNULL extends BranchInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | Zobject ref = frame.getOperandStack().popRef(); 17 | if (ref == null) { 18 | BranchLogic.branch(frame, offset); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/Load.java: -------------------------------------------------------------------------------- 1 | package instructions.loads; 2 | 3 | import runtimedata.Zframe; 4 | import runtimedata.heap.Zobject; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 工具类,为不同的数据类型提供不同的加载机制; 10 | * 总体原则是:先从本地变量表中取出变量,然后将该变量压入到操作数栈中; 11 | */ 12 | public class Load { 13 | public static void aload(Zframe frame, int index) { 14 | Zobject ref = frame.getLocalVars().getRef(index); 15 | frame.getOperandStack().pushRef(ref); 16 | } 17 | 18 | public static void dload(Zframe frame, int index) { 19 | double val = frame.getLocalVars().getDouble(index); 20 | frame.getOperandStack().pushDouble(val); 21 | } 22 | 23 | public static void fload(Zframe frame, int index) { 24 | float val = frame.getLocalVars().getFloat(index); 25 | frame.getOperandStack().pushFloat(val); 26 | } 27 | 28 | public static void iload(Zframe frame, int index) { 29 | int val = frame.getLocalVars().getInt(index); 30 | frame.getOperandStack().pushInt(val); 31 | } 32 | 33 | public static void lload(Zframe frame, int index) { 34 | long val = frame.getLocalVars().getLong(index); 35 | frame.getOperandStack().pushLong(val); 36 | } 37 | 38 | //用在 load 数组元素时,检测数组是否为 null 39 | public static void checkNotNull(Zobject arrRef) { 40 | if (arrRef == null) { 41 | throw new NullPointerException(); 42 | } 43 | } 44 | 45 | public static void checkIndex(int count, int index) { 46 | if (index < 0 || index >= count) { 47 | throw new ArrayIndexOutOfBoundsException("index: " + index + " array's count: " + count); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loaddouble/DLOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loaddouble; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DLOAD extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.dload(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loaddouble/DLOAD_0.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loaddouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DLOAD_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.dload(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loaddouble/DLOAD_1.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loaddouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DLOAD_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.dload(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loaddouble/DLOAD_2.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loaddouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DLOAD_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.dload(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loaddouble/DLOAD_3.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loaddouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DLOAD_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.dload(frame, 3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadfloat/FLOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadfloat; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FLOAD extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.fload(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadfloat/FLOAD_0.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadfloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FLOAD_0 extends NoOperandsInstruction{ 13 | 14 | @Override 15 | public void execute(Zframe frame) { 16 | Load.fload(frame,0); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadfloat/FLOAD_1.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadfloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FLOAD_1 extends NoOperandsInstruction{ 13 | 14 | @Override 15 | public void execute(Zframe frame) { 16 | Load.fload(frame,1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadfloat/FLOAD_2.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadfloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FLOAD_2 extends NoOperandsInstruction{ 13 | 14 | @Override 15 | public void execute(Zframe frame) { 16 | Load.fload(frame,2); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadfloat/FLOAD_3.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadfloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FLOAD_3 extends NoOperandsInstruction { 13 | 14 | @Override 15 | public void execute(Zframe frame) { 16 | Load.fload(frame, 3); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadint/ILOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadint; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ILOAD extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.iload(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadint/ILOAD_0.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ILOAD_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.iload(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadint/ILOAD_1.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ILOAD_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.iload(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadint/ILOAD_2.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ILOAD_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.iload(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadint/ILOAD_3.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ILOAD_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.iload(frame, 3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadlong/LLOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadlong; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LLOAD extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.lload(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadlong/LLOAD_0.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadlong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LLOAD_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.lload(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadlong/LLOAD_1.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadlong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LLOAD_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.lload(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadlong/LLOAD_2.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadlong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LLOAD_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.lload(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadlong/LLOAD_3.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadlong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LLOAD_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.lload(frame, 3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadref/ALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadref; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ALOAD extends Index8Instruction{ 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.aload(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadref/ALOAD_0.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ALOAD_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.aload(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadref/ALOAD_1.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ALOAD_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.aload(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadref/ALOAD_2.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ALOAD_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.aload(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadref/ALOAD_3.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ALOAD_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Load.aload(frame,3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/AALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值(非基本类型):eg String s = str[2]; 13 | */ 14 | public class AALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | Zobject[] refs = arrRef.getRefs(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushRef(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/BALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg byte b = bytes[2]; 13 | */ 14 | public class BALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | byte[] refs = arrRef.getBytes(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushInt(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/CALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg char c = chars[2]; 13 | */ 14 | public class CALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | char[] refs = arrRef.getChars(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushInt(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/DALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg double d = doubles[2]; 13 | */ 14 | public class DALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | double[] refs = arrRef.getDoubles(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushDouble(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/FALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg float b = floats[2]; 13 | */ 14 | public class FALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | float[] refs = arrRef.getFloats(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushFloat(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/IALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg int i = ints[2]; 13 | */ 14 | public class IALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | int[] refs = arrRef.getInts(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushInt(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/LALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg long l = longs[2]; 13 | */ 14 | public class LALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | long[] refs = arrRef.getLongs(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushLong(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/loads/loadxarr/SALOAD.java: -------------------------------------------------------------------------------- 1 | package instructions.loads.loadxarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.loads.Load; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * 获取数组指定索引值:eg short s = shorts[2]; 13 | */ 14 | public class SALOAD extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //数组元素的索引值 19 | int index = operandStack.popInt(); 20 | //数组对象的引用 21 | Zobject arrRef = operandStack.popRef(); 22 | 23 | Load.checkNotNull(arrRef); 24 | //得到数组对象 25 | short[] refs = arrRef.getShorts(); 26 | Load.checkIndex(arrRef.getArrayLen(), index); 27 | //将数组的 index 的值压栈 28 | operandStack.pushInt(refs[index]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/math/add/DADD.java: -------------------------------------------------------------------------------- 1 | package instructions.math.add; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DADD extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val1 = stack.popDouble(); 17 | double val2 = stack.popDouble(); 18 | double res = val1 + val2; 19 | stack.pushDouble(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/add/FADD.java: -------------------------------------------------------------------------------- 1 | package instructions.math.add; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FADD extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val1 = stack.popFloat(); 17 | float val2 = stack.popFloat(); 18 | float res = val1 + val2; 19 | stack.pushFloat(res); 20 | } 21 | } -------------------------------------------------------------------------------- /Java/src/instructions/math/add/IADD.java: -------------------------------------------------------------------------------- 1 | package instructions.math.add; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IADD extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | int val2 = stack.popInt(); 18 | int res = val1 + val2; 19 | stack.pushInt(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/add/LADD.java: -------------------------------------------------------------------------------- 1 | package instructions.math.add; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LADD extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val1 = stack.popLong(); 17 | long val2 = stack.popLong(); 18 | long res = val1 + val2; 19 | stack.pushLong(res); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Java/src/instructions/math/and/IAND.java: -------------------------------------------------------------------------------- 1 | package instructions.math.and; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IAND extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); 17 | int val1 = stack.popInt(); 18 | int res = val1 & val2; 19 | stack.pushInt(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/and/LAND.java: -------------------------------------------------------------------------------- 1 | package instructions.math.and; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LAND extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | long val1 = stack.popLong(); 18 | long res = val1 & val2; 19 | stack.pushLong(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/div/DDIV.java: -------------------------------------------------------------------------------- 1 | package instructions.math.div; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DDIV extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val2 = stack.popDouble(); 17 | double val1 = stack.popDouble(); 18 | double res = val1 / val2; 19 | stack.pushDouble(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/div/FDIV.java: -------------------------------------------------------------------------------- 1 | package instructions.math.div; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FDIV extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val2 = stack.popFloat(); 17 | float val1 = stack.popFloat(); 18 | float res = val1 / val2; 19 | stack.pushFloat(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/div/IDIV.java: -------------------------------------------------------------------------------- 1 | package instructions.math.div; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IDIV extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); 17 | int val1 = stack.popInt(); 18 | int res = val1 / val2; 19 | stack.pushInt(res); 20 | } 21 | } -------------------------------------------------------------------------------- /Java/src/instructions/math/div/LDIV.java: -------------------------------------------------------------------------------- 1 | package instructions.math.div; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LDIV extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | long val1 = stack.popLong(); 18 | long res = val1 / val2; 19 | stack.pushLong(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/iinc/IINC.java: -------------------------------------------------------------------------------- 1 | package instructions.math.iinc; 2 | 3 | import instructions.base.BytecodeReader; 4 | import instructions.base.Instruction; 5 | import runtimedata.LocalVars; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: iinc指令给局部变量表中的int变量增加常量值,局部变量表索引和常量值都由指令的操作数提供。 12 | */ 13 | public class IINC implements Instruction { 14 | public int index; 15 | public int offset; 16 | 17 | @Override 18 | public void fetchOperands(BytecodeReader reader) { 19 | index = reader.readUint8(); 20 | offset = reader.readInt8(); 21 | } 22 | 23 | @Override 24 | public void execute(Zframe frame) { 25 | LocalVars localVars = frame.getLocalVars(); 26 | int val = localVars.getInt(index); 27 | val += offset; 28 | localVars.setInt(index, val); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/math/mul/DMUL.java: -------------------------------------------------------------------------------- 1 | package instructions.math.mul; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DMUL extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val1 = stack.popDouble(); 17 | double val2 = stack.popDouble(); 18 | double res = val1 * val2; 19 | stack.pushDouble(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/mul/FMUL.java: -------------------------------------------------------------------------------- 1 | package instructions.math.mul; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FMUL extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val1 = stack.popFloat(); 17 | float val2 = stack.popFloat(); 18 | float res = val1 * val2; 19 | stack.pushFloat(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/mul/IMUL.java: -------------------------------------------------------------------------------- 1 | package instructions.math.mul; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IMUL extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val1 = stack.popInt(); 17 | int val2 = stack.popInt(); 18 | int res = val1 * val2; 19 | stack.pushInt(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/mul/LMUL.java: -------------------------------------------------------------------------------- 1 | package instructions.math.mul; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LMUL extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val1 = stack.popLong(); 17 | long val2 = stack.popLong(); 18 | long res = val1 * val2; 19 | stack.pushLong(res); 20 | } 21 | } -------------------------------------------------------------------------------- /Java/src/instructions/math/neg/DNEG.java: -------------------------------------------------------------------------------- 1 | package instructions.math.neg; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DNEG extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val = stack.popDouble(); 17 | stack.pushDouble(-val); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/math/neg/FNEG.java: -------------------------------------------------------------------------------- 1 | package instructions.math.neg; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FNEG extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val = stack.popFloat(); 17 | stack.pushFloat(-val); 18 | } 19 | } -------------------------------------------------------------------------------- /Java/src/instructions/math/neg/INEG.java: -------------------------------------------------------------------------------- 1 | package instructions.math.neg; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class INEG extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val = stack.popInt(); 17 | stack.pushInt(-val); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/math/neg/LNEG.java: -------------------------------------------------------------------------------- 1 | package instructions.math.neg; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LNEG extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val = stack.popLong(); 17 | stack.pushLong(-val); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Java/src/instructions/math/or/IOR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.or; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IOR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); 17 | int val1 = stack.popInt(); 18 | int res = val1 | val2; 19 | stack.pushInt(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/or/LOR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.or; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LOR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | long val1 = stack.popLong(); 18 | long res = val1 | val2; 19 | stack.pushLong(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/rem/DREM.java: -------------------------------------------------------------------------------- 1 | package instructions.math.rem; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DREM extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val2 = stack.popDouble(); 17 | double val1 = stack.popDouble(); 18 | double res = val1 % val2; 19 | stack.pushDouble(res); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /Java/src/instructions/math/rem/FREM.java: -------------------------------------------------------------------------------- 1 | package instructions.math.rem; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FREM extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val2 = stack.popFloat(); 17 | float val1 = stack.popFloat(); 18 | float res = val1 % val2; 19 | stack.pushFloat(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/rem/IREM.java: -------------------------------------------------------------------------------- 1 | package instructions.math.rem; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IREM extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); 17 | int val1 = stack.popInt(); 18 | if (val2 == 0) { 19 | throw new ArithmeticException("java.lang.ArithmeticException: / by zero"); 20 | } 21 | int res = val1 % val2; 22 | stack.pushInt(res); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Java/src/instructions/math/rem/LREM.java: -------------------------------------------------------------------------------- 1 | package instructions.math.rem; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LREM extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | if (val2 == 0) { 18 | throw new ArithmeticException("java.lang.ArithmeticException: / by zero"); 19 | } 20 | long val1 = stack.popLong(); 21 | long res = val1 % val2; 22 | stack.pushLong(res); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sh/ISHL.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sh; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: int 左位移 11 | * 先从操作数栈中弹出两个int变量v2和v1。v1是要进行位移操作的变量,v2指出要移位多少比特。 12 | */ 13 | public class ISHL extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | int val2 = stack.popInt(); //要移动多少bit 18 | int val1 = stack.popInt(); //要进行位移操作的变量 19 | int s = val2 & 0x1f; //int变量只有32位,所以只取val2的后5个比特就足够表示位移位数了,位移操作符右侧必须是无符号整数,所以需要对val2进行类型转换 20 | 21 | //但是Java中对于大数左移超出后,也会变成负数,所以这里不做额外处理了 22 | int res = val1 << s; 23 | 24 | stack.pushInt(res); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sh/ISHR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sh; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 算术右移,需要扩展符号位,使用最高位填充移位后左侧的空位。 11 | */ 12 | public class ISHR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); //要移动多少bit 17 | int val1 = stack.popInt(); //要进行位移操作的变量 18 | int s = val2 & 0x1f; 19 | int res = val1 >> s; 20 | stack.pushInt(res); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sh/IUSHR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sh; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 逻辑右移,或叫无符号右移运算符“>>>“只对位进行操作,没有算术含义,它用0填充左侧的空位。 11 | */ 12 | public class IUSHR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); //要移动多少bit 17 | int val1 = stack.popInt(); //要进行位移操作的变量 18 | int s = val2 & 0x1f; 19 | int res = val1 >>> s; 20 | stack.pushInt(res); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sh/LSHL.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sh; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: int 左位移 11 | * 先从操作数栈中弹出两个int变量v2和v1。v1是要进行位移操作的变量,v2指出要移位多少比特。 12 | */ 13 | public class LSHL extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | int val2 = stack.popInt(); //要移动多少bit 18 | long val1 = stack.popLong(); //要进行位移操作的变量 19 | int s = val2 & 0x3f; //int变量只有32位,所以只取val2的后5个比特就足够表示位移位数了,位移操作符右侧必须是无符号整数,所以需要对val2进行类型转换 20 | 21 | //但是Java中对于大数左移超出后,也会变成负数,所以这里不做额外处理了 22 | long res = val1 << s; 23 | 24 | stack.pushLong(res); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sh/LSHR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sh; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: int 左位移 11 | * 先从操作数栈中弹出两个int变量v2和v1。v1是要进行位移操作的变量,v2指出要移位多少比特。 12 | */ 13 | public class LSHR extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | int val2 = stack.popInt(); //要移动多少bit 18 | long val1 = stack.popLong(); //要进行位移操作的变量 19 | int s = val2 & 0x3f; //int变量只有32位,所以只取val2的后5个比特就足够表示位移位数了,位移操作符右侧必须是无符号整数,所以需要对val2进行类型转换 20 | 21 | //但是Java中对于大数左移超出后,也会变成负数,所以这里不做额外处理了 22 | long res = val1 >> s; 23 | 24 | stack.pushLong(res); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sh/LUSHR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sh; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 逻辑右移,或叫无符号右移运算符“>>>“只对位进行操作,没有算术含义,它用0填充左侧的空位。 11 | */ 12 | public class LUSHR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); //要移动多少bit 17 | long val1 = stack.popLong(); //要进行位移操作的变量 18 | int s = val2 & 0x3f; //int变量只有32位,所以只取val2的后5个比特就足够表示位移位数了,位移操作符右侧必须是无符号整数,所以需要对val2进行类型转换 19 | 20 | //但是Java中对于大数左移超出后,也会变成负数,所以这里不做额外处理了 21 | long res = val1 >>> s; 22 | 23 | stack.pushLong(res); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sub/DSUB.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sub; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DSUB extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | double val2 = stack.popDouble(); 17 | double val1 = stack.popDouble(); 18 | double res = val1 - val2; 19 | stack.pushDouble(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sub/FSUB.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sub; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FSUB extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | float val2 = stack.popFloat(); 17 | float val1 = stack.popFloat(); 18 | float res = val1 - val2; 19 | stack.pushFloat(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/sub/ISUB.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sub; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ISUB extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); 17 | int val1 = stack.popInt(); 18 | int res = val1 - val2; 19 | stack.pushInt(res); 20 | } 21 | } -------------------------------------------------------------------------------- /Java/src/instructions/math/sub/LSUB.java: -------------------------------------------------------------------------------- 1 | package instructions.math.sub; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LSUB extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | long val1 = stack.popLong(); 18 | long res = val1 - val2; 19 | stack.pushLong(res); 20 | } 21 | } -------------------------------------------------------------------------------- /Java/src/instructions/math/xor/IXOR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.xor; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class IXOR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | int val2 = stack.popInt(); 17 | int val1 = stack.popInt(); 18 | int res = val1 ^ val2; 19 | stack.pushInt(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/math/xor/LXOR.java: -------------------------------------------------------------------------------- 1 | package instructions.math.xor; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LXOR extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | long val2 = stack.popLong(); 17 | long val1 = stack.popLong(); 18 | long res = val1 ^ val2; 19 | stack.pushLong(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/references/ANEW_ARRAY.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.Index16Instruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.ClassRef; 7 | import runtimedata.heap.RuntimeConstantPool; 8 | import runtimedata.heap.Zclass; 9 | import runtimedata.heap.Zobject; 10 | 11 | /** 12 | * @author zachaxy 13 | * @date 17/12/29 14 | * desc:创建引用类型数组,注意这里是一维的!!! 15 | * 如果创建的是 String[],那么从运行时常量池拿到 String 的符号引用,通过符号引用将 String 类加载进来 16 | * 接下来再将 String[] 类加载进来! 17 | * 最后通过 String[] 类创建 字符串数组对象,并压入操作数栈 18 | */ 19 | public class ANEW_ARRAY extends Index16Instruction { 20 | @Override 21 | public void execute(Zframe frame) { 22 | RuntimeConstantPool runtimeConstantPool = frame.getMethod().getClazz().getRuntimeConstantPool(); 23 | //首先获取到该数组的引用类型;eg:String [] arr = new String[2]; 那么获取到的类是:java.lang.String 24 | ClassRef classRef = (ClassRef) runtimeConstantPool.getRuntimeConstant(this.index).getValue(); 25 | 26 | //该引用类型若没加载过,那么先将该引用类型加载进来; 27 | Zclass componentClass = classRef.resolvedClass(); 28 | 29 | OperandStack operandStack = frame.getOperandStack(); 30 | int count = operandStack.popInt(); 31 | if (count < 0) { 32 | throw new NegativeArraySizeException("" + count); 33 | } 34 | //根据基础类型:java/lang/String,得到数组类[Ljava/lang/String; 35 | Zclass arrClazz = componentClass.arrayClass(); 36 | //根据数组类去创建具体的数组对象; 37 | Zobject arr = arrClazz.newArray(count); 38 | operandStack.pushRef(arr); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Java/src/instructions/references/ARRAY_LENGTH.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.Zobject; 7 | 8 | /** 9 | * @author zachaxy 10 | * @date 17/12/29 11 | * desc:获取数组长度的指令 12 | */ 13 | public class ARRAY_LENGTH extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack operandStack = frame.getOperandStack(); 17 | Zobject arrRef = operandStack.popRef(); 18 | if (arrRef == null) { 19 | throw new NullPointerException("called length on a null Object"); 20 | } 21 | int arrLen = arrRef.getArrayLen(); 22 | operandStack.pushInt(arrLen); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Java/src/instructions/references/CHECK_CAST.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.Index16Instruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.ClassRef; 7 | import runtimedata.heap.RuntimeConstantPool; 8 | import runtimedata.heap.Zclass; 9 | import runtimedata.heap.Zobject; 10 | 11 | /** 12 | * @author zachaxy 13 | * @date 17/12/26 14 | * desc:类型转换,该指令和instanceof指令的区别在于,instanceof判断后将结果压入操作数栈,而cast直接抛出异常 15 | * String str = (String)obj 16 | * NOTE:checkcast 指令,在pop到引用 obj 之后,又将 obj push 到栈中!!! 17 | */ 18 | public class CHECK_CAST extends Index16Instruction { 19 | @Override 20 | public void execute(Zframe frame) { 21 | OperandStack stack = frame.getOperandStack(); 22 | Zobject obj = stack.popRef(); 23 | stack.pushRef(obj); 24 | //如果 obj 为 null,则可以转换为任意类型 25 | if (obj == null) { 26 | return; 27 | } 28 | 29 | RuntimeConstantPool runtimeConstantPool = frame.getMethod().getClazz().getRuntimeConstantPool(); 30 | ClassRef classRef = (ClassRef) runtimeConstantPool.getRuntimeConstant(index).getValue(); 31 | Zclass clazz = classRef.resolvedClass(); 32 | if (!obj.isInstanceOf(clazz)) { 33 | throw new ClassCastException(obj.getClazz().thisClassName + " can't cast to " + clazz.thisClassName); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Java/src/instructions/references/INSTANCE_OF.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.Index16Instruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.ClassRef; 7 | import runtimedata.heap.RuntimeConstantPool; 8 | import runtimedata.heap.Zclass; 9 | import runtimedata.heap.Zobject; 10 | 11 | /** 12 | * Author: zhangxin 13 | * Time: 2017/7/26. 14 | * Desc: java 中的 instanceof 关键字,会被解析成 INSTANCE_OF 指令 eg:(obj instanceof Object) 15 | * 将判断的结果写入操作数栈 16 | */ 17 | public class INSTANCE_OF extends Index16Instruction { 18 | @Override 19 | public void execute(Zframe frame) { 20 | OperandStack stack = frame.getOperandStack(); 21 | Zobject obj = stack.popRef(); 22 | //如果 obj 为 null,对任何 class 类型的判断都是 false; 23 | if (obj == null) { 24 | stack.pushInt(0); 25 | return; 26 | } 27 | 28 | RuntimeConstantPool runtimeConstantPool = frame.getMethod().getClazz().getRuntimeConstantPool(); 29 | ClassRef classRef = (ClassRef) runtimeConstantPool.getRuntimeConstant(index).getValue(); 30 | Zclass clazz = classRef.resolvedClass(); 31 | //obj是不是class的实例 32 | if (obj.isInstanceOf(clazz)) { 33 | stack.pushInt(1); 34 | } else { 35 | stack.pushInt(0); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Java/src/instructions/references/INVOKE_NATIVE.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | import runtimedata.heap.Zmethod; 6 | import znative.NativeMethod; 7 | import znative.RegisterCenter; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 18/1/2 12 | * desc:nativie 方法执行的指令 13 | */ 14 | public class INVOKE_NATIVE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | Zmethod method = frame.getMethod(); 18 | String clazzName = method.getClazz().thisClassName; 19 | String methodName = method.getName(); 20 | String descriptor = method.getDescriptor(); 21 | 22 | NativeMethod nativeMethod = RegisterCenter.findNativeMethod(clazzName, methodName, descriptor); 23 | if (nativeMethod == null) { 24 | String methodInfo = clazzName + "." + methodName + descriptor; 25 | throw new UnsatisfiedLinkError(methodInfo); 26 | } 27 | 28 | nativeMethod.run(frame); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Java/src/instructions/references/INVOKE_STATIC.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.ClassInitLogic; 4 | import instructions.base.Index16Instruction; 5 | import instructions.base.MethodInvokeLogic; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.MethodRef; 8 | import runtimedata.heap.RuntimeConstantPool; 9 | import runtimedata.heap.Zclass; 10 | import runtimedata.heap.Zmethod; 11 | 12 | /** 13 | * @author zachaxy 14 | * @date 17/12/27 15 | * desc:静态方法调用指令 16 | * 静态方法,在调用阶段即可确定是哪个方法 17 | */ 18 | public class INVOKE_STATIC extends Index16Instruction { 19 | @Override 20 | public void execute(Zframe frame) { 21 | RuntimeConstantPool runtimeConstantPool = frame.getMethod().getClazz().getRuntimeConstantPool(); 22 | //通过index,拿到方法符号引用 23 | MethodRef methodRef = (MethodRef) runtimeConstantPool.getRuntimeConstant(index).getValue(); 24 | Zmethod resolvedMethod = methodRef.resolvedMethod(); 25 | if (!resolvedMethod.isStatic()) { 26 | throw new IncompatibleClassChangeError(); 27 | } 28 | 29 | Zclass clazz = resolvedMethod.getClazz(); 30 | //判断其Class是否已经加载过,如果还未加载,那么调用其类的方法压栈 31 | if (!clazz.isInitStarted()) { 32 | //当前指令已经是在执行new了,但是类还没有加载,所以当前帧先回退,让类初始化的帧入栈,等类初始化完成后,重新执行new; 33 | frame.revertNextPC(); 34 | ClassInitLogic.initClass(frame.getThread(), clazz); 35 | return; 36 | } 37 | 38 | MethodInvokeLogic.invokeMethod(frame, resolvedMethod); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Java/src/instructions/references/NEW.java: -------------------------------------------------------------------------------- 1 | package instructions.references; 2 | 3 | import instructions.base.ClassInitLogic; 4 | import instructions.base.Index16Instruction; 5 | import runtimedata.Zframe; 6 | import runtimedata.heap.ClassRef; 7 | import runtimedata.heap.RuntimeConstantPool; 8 | import runtimedata.heap.Zclass; 9 | import runtimedata.heap.Zobject; 10 | 11 | /** 12 | * Author: zhangxin 13 | * Time: 2017/7/24. 14 | * Desc: uint16的索引,来自字节码,通过该索引,从当前类的运行时常量池中找到类符号引用; 15 | * 解析该类符号引用,可以拿到类数据,然后创建对象,并把对象引用压入操作数栈; 16 | */ 17 | public class NEW extends Index16Instruction { 18 | 19 | @Override 20 | public void execute(Zframe frame) { 21 | RuntimeConstantPool runtimeConstantPool = frame.getMethod().getClazz().getRuntimeConstantPool(); 22 | ClassRef classRef = (ClassRef) runtimeConstantPool.getRuntimeConstant(index).getValue(); 23 | Zclass clazz = classRef.resolvedClass(); 24 | 25 | //判断其Class是否已经加载过,如果还未加载,那么调用其类的方法压栈 26 | if (!clazz.isInitStarted()) { 27 | //当前指令已经是在执行new了,但是类还没有加载,所以当前帧先回退,让类初始化的帧入栈,等类初始化完成后,重新执行new; 28 | frame.revertNextPC(); 29 | ClassInitLogic.initClass(frame.getThread(), clazz); 30 | return; 31 | } 32 | 33 | if(clazz.isInterface() || clazz.isAbstract()){ 34 | throw new InstantiationError(clazz.thisClassName + " can't new"); 35 | } 36 | 37 | Zobject ref = clazz.newObject(); 38 | frame.getOperandStack().pushRef(ref); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/dup/DUP.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.dup; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: DUP指令复制栈顶的单个变量 12 | */ 13 | public class DUP extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot = stack.popSlot(); 18 | stack.pushSlot(slot); 19 | stack.pushSlot(slot); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/dup/DUP2.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.dup; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: b a => b a b a; 12 | */ 13 | public class DUP2 extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot1 = stack.popSlot(); 18 | Slot slot2 = stack.popSlot(); 19 | stack.pushSlot(slot2); 20 | stack.pushSlot(slot1); 21 | stack.pushSlot(slot2); 22 | stack.pushSlot(slot1); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/dup/DUP2_X1.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.dup; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: 12 | */ 13 | public class DUP2_X1 extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot1 = stack.popSlot(); 18 | Slot slot2 = stack.popSlot(); 19 | Slot slot3 = stack.popSlot(); 20 | 21 | stack.pushSlot(slot2); 22 | stack.pushSlot(slot1); 23 | stack.pushSlot(slot3); 24 | stack.pushSlot(slot2); 25 | stack.pushSlot(slot1); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/dup/DUP2_X2.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.dup; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: 12 | */ 13 | public class DUP2_X2 extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot1 = stack.popSlot(); 18 | Slot slot2 = stack.popSlot(); 19 | Slot slot3 = stack.popSlot(); 20 | Slot slot4 = stack.popSlot(); 21 | 22 | stack.pushSlot(slot2); 23 | stack.pushSlot(slot1); 24 | stack.pushSlot(slot4); 25 | stack.pushSlot(slot3); 26 | stack.pushSlot(slot2); 27 | stack.pushSlot(slot1); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/dup/DUP_X1.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.dup; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: DUP_X1 指令 先将栈顶的两个变量交换,然后再将原栈顶元素添加到栈顶 ab => bab; 12 | */ 13 | public class DUP_X1 extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot1 = stack.popSlot(); 18 | Slot slot2 = stack.popSlot(); 19 | stack.pushSlot(slot1); 20 | stack.pushSlot(slot2); 21 | stack.pushSlot(slot1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/dup/DUP_X2.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.dup; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: 3 2 1 => 1 3 2 1; 12 | */ 13 | public class DUP_X2 extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot1 = stack.popSlot(); 18 | Slot slot2 = stack.popSlot(); 19 | Slot slot3 = stack.popSlot(); 20 | stack.pushSlot(slot1); 21 | stack.pushSlot(slot3); 22 | stack.pushSlot(slot2); 23 | stack.pushSlot(slot1); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/pop/POP.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.pop; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.Zframe; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: pop指令把栈顶变量弹出 10 | * 只能用于弹出int、float等占用一个操作数栈位置的变量 11 | */ 12 | public class POP extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | frame.getOperandStack().popSlot(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/pop/POP2.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.pop; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: double和long变量在操作数栈中占据两个位置,需要使用pop2指令弹出 11 | */ 12 | public class POP2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | OperandStack stack = frame.getOperandStack(); 16 | stack.popSlot(); 17 | stack.popSlot(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Java/src/instructions/stack/swap/SWAP.java: -------------------------------------------------------------------------------- 1 | package instructions.stack.swap; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import runtimedata.OperandStack; 5 | import runtimedata.Slot; 6 | import runtimedata.Zframe; 7 | 8 | /** 9 | * Author: zhangxin 10 | * Time: 2017/5/5 0005. 11 | * Desc: swap指令交换栈顶的两个变量 12 | */ 13 | public class SWAP extends NoOperandsInstruction { 14 | @Override 15 | public void execute(Zframe frame) { 16 | OperandStack stack = frame.getOperandStack(); 17 | Slot slot1 = stack.popSlot(); 18 | Slot slot2 = stack.popSlot(); 19 | 20 | stack.pushSlot(slot1); 21 | stack.pushSlot(slot2); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/Store.java: -------------------------------------------------------------------------------- 1 | package instructions.stores; 2 | 3 | import runtimedata.Zframe; 4 | import runtimedata.heap.Zobject; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/5 0005. 9 | * Desc: 存储指令工具类,针对引用,int,long,double,float五种类型; 10 | */ 11 | public class Store { 12 | public static void astore(Zframe frame, int index) { 13 | Zobject ref = frame.getOperandStack().popRef(); 14 | frame.getLocalVars().setRef(index, ref); 15 | } 16 | 17 | public static void istore(Zframe frame, int index) { 18 | int val = frame.getOperandStack().popInt(); 19 | frame.getLocalVars().setInt(index, val); 20 | } 21 | 22 | public static void lstore(Zframe frame, int index) { 23 | long val = frame.getOperandStack().popLong(); 24 | frame.getLocalVars().setLong(index, val); 25 | } 26 | 27 | public static void fstore(Zframe frame, int index) { 28 | float val = frame.getOperandStack().popFloat(); 29 | frame.getLocalVars().setFloat(index, val); 30 | } 31 | 32 | public static void dstote(Zframe frame, int index) { 33 | double val = frame.getOperandStack().popDouble(); 34 | frame.getLocalVars().setDouble(index, val); 35 | } 36 | 37 | //用在 store 数组元素时,检测数组是否为 null 38 | public static void checkNotNull(Zobject arrRef) { 39 | if (arrRef == null) { 40 | throw new NullPointerException(); 41 | } 42 | } 43 | 44 | public static void checkIndex(int count, int index) { 45 | if (index < 0 || index >= count) { 46 | throw new ArrayIndexOutOfBoundsException("index: " + index + " array's count: " + count); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storedouble/DSTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storedouble; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DSTORE extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.dstote(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storedouble/DSTORE_0.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storedouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DSTORE_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.dstote(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storedouble/DSTORE_1.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storedouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DSTORE_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.dstote(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storedouble/DSTORE_2.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storedouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DSTORE_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.dstote(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storedouble/DSTORE_3.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storedouble; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class DSTORE_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.dstote(frame,3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storefloat/FSTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storefloat; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FSTORE extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.fstore(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storefloat/FSTORE_0.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storefloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FSTORE_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.fstore(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storefloat/FSTORE_1.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storefloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FSTORE_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.fstore(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storefloat/FSTORE_2.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storefloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FSTORE_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.fstore(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storefloat/FSTORE_3.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storefloat; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class FSTORE_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.fstore(frame,3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeint/ISTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeint; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ISTORE extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.istore(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeint/ISTORE_0.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ISTORE_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.istore(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeint/ISTORE_1.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ISTORE_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.istore(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeint/ISTORE_2.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ISTORE_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.istore(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeint/ISTORE_3.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeint; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ISTORE_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.istore(frame,3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storelong/LSTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storelong; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LSTORE extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.lstore(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storelong/LSTORE_0.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storelong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LSTORE_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.lstore(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storelong/LSTORE_1.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storelong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LSTORE_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.lstore(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storelong/LSTORE_2.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storelong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LSTORE_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.lstore(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storelong/LSTORE_3.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storelong; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class LSTORE_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.lstore(frame,3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeref/ASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeref; 2 | 3 | import instructions.base.Index8Instruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ASTORE extends Index8Instruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.astore(frame,index); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeref/ASTORE_0.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ASTORE_0 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.astore(frame,0); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeref/ASTORE_1.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ASTORE_1 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.astore(frame,1); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeref/ASTORE_2.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ASTORE_2 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.astore(frame,2); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storeref/ASTORE_3.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storeref; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.Zframe; 6 | 7 | /** 8 | * Author: zhangxin 9 | * Time: 2017/5/5 0005. 10 | * Desc: 11 | */ 12 | public class ASTORE_3 extends NoOperandsInstruction { 13 | @Override 14 | public void execute(Zframe frame) { 15 | Store.astore(frame,3); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/AASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class AASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | Zobject val = operandStack.popRef(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | Zobject[] refs = arrRef.getRefs(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/BASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class BASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | byte val = (byte) operandStack.popInt(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | byte[] refs = arrRef.getBytes(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/CASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class CASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | char val = (char) operandStack.popInt(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | char[] refs = arrRef.getChars(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/DASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class DASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | double val = operandStack.popDouble(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | double[] refs = arrRef.getDoubles(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/FASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class FASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | float val = operandStack.popFloat(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | float[] refs = arrRef.getFloats(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/IASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class IASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | int val = operandStack.popInt(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | int[] refs = arrRef.getInts(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/LASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class LASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | long val = operandStack.popLong(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | long[] refs = arrRef.getLongs(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/instructions/stores/storexarr/SASTORE.java: -------------------------------------------------------------------------------- 1 | package instructions.stores.storexarr; 2 | 3 | import instructions.base.NoOperandsInstruction; 4 | import instructions.stores.Store; 5 | import runtimedata.OperandStack; 6 | import runtimedata.Zframe; 7 | import runtimedata.heap.Zobject; 8 | 9 | /** 10 | * @author zachaxy 11 | * @date 17/12/29 12 | * desc:对数组某一元素的赋值 x[0] = y 13 | */ 14 | public class SASTORE extends NoOperandsInstruction { 15 | @Override 16 | public void execute(Zframe frame) { 17 | OperandStack operandStack = frame.getOperandStack(); 18 | //所要赋的值 19 | short val = (short) operandStack.popInt(); 20 | //数组索引 21 | int index = operandStack.popInt(); 22 | //数组对象的引用 23 | Zobject arrRef = operandStack.popRef(); 24 | 25 | Store.checkNotNull(arrRef); 26 | //得到数组对象 27 | short[] refs = arrRef.getShorts(); 28 | Store.checkIndex(arrRef.getArrayLen(), index); 29 | //将数组的 index 的元素进行赋值 30 | refs[index] = val; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/runtimedata/LocalVars.java: -------------------------------------------------------------------------------- 1 | package runtimedata; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/4 0004. 6 | * Desc: 局部变量表是按索引访问的,所以很自然,可以把它想象成一个数组。 7 | * 根据Java虚拟机规范,这个数组的每个元素至少可以容纳一个int或引用值,两个连续的元素可以容纳一个long或double值。 8 | * 注:这里并没有真的对boolean、byte、short和char类型定义存取方法,因为这些类型的值都是转换成int值类来处理的(4K对齐) 9 | */ 10 | public class LocalVars extends Slots { 11 | public LocalVars(int size) { 12 | super(size); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Java/src/runtimedata/Slot.java: -------------------------------------------------------------------------------- 1 | package runtimedata; 2 | 3 | import runtimedata.heap.Zobject; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/4 0004. 8 | * Desc:局部变量表的数据,根据Java虚拟机规范,这个数组的每个元素至少可以容纳一个int或引用值,两个连续的元素可以容纳一个long或double值。 9 | * 可问题是用什么数据结构来存储,目前并没有很好的方法,只能将这个类设计为既包含一个int有包含一个引用,但是在真正使用的时候,二者只会用其一 10 | * 导致了一半内存的浪费; 11 | */ 12 | public class Slot { 13 | public int num; 14 | public Zobject ref; 15 | 16 | public Slot() {} 17 | } 18 | -------------------------------------------------------------------------------- /Java/src/runtimedata/Slots.java: -------------------------------------------------------------------------------- 1 | package runtimedata; 2 | 3 | import runtimedata.heap.Zobject; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/7/22. 8 | * Desc: Slots 封装,针对静态变量表,在申请完空间后,如果没有显式赋值,那么获取值应该为0或 null 9 | * 然而 Slot[] 在创建完后,并不具备上述功能 10 | * 因此在构造方法中,Slot[] 创建完后,再为其每一个元素都创建一个 slot 对象, 11 | * 这样在没有为静态变量赋值时,访问Slot[]的元素时,不会引发空指针异常! 12 | */ 13 | public class Slots { 14 | private Slot[] slots; 15 | 16 | public Slots(int size) { 17 | slots = new Slot[size]; 18 | for (int i = 0; i < size; i++) { 19 | slots[i] = new Slot(); 20 | } 21 | } 22 | 23 | //提供了对int,float,long,double,引用的存取,这里要注意的是long和double是占用8字节的,所以使用了局部变量表中的两个槽位分别存储前四字节和后四字节 24 | public void setInt(int index, int val) { 25 | slots[index].num = val; 26 | } 27 | 28 | public int getInt(int index) { 29 | return slots[index].num; 30 | } 31 | 32 | public void setFloat(int index, float val) { 33 | slots[index].num = Float.floatToIntBits(val); 34 | } 35 | 36 | public float getFloat(int index) { 37 | return Float.intBitsToFloat(slots[index].num); 38 | } 39 | 40 | public void setLong(int index, long val) { 41 | //先存低32位 42 | slots[index].num = (int) (val); 43 | //再存高32位 44 | slots[index + 1].num = (int) (val >> 32); 45 | } 46 | 47 | public long getLong(int index) { 48 | int low = slots[index].num; 49 | long high = slots[index + 1].num; 50 | return ((high & 0x000000ffffffffL) << 32) | (low & 0x00000000ffffffffL); 51 | } 52 | 53 | public void setDouble(int index, double val) { 54 | long bits = Double.doubleToLongBits(val); 55 | setLong(index, bits); 56 | } 57 | 58 | public double getDouble(int index) { 59 | long bits = getLong(index); 60 | return Double.longBitsToDouble(bits); 61 | } 62 | 63 | public void setRef(int index, Zobject ref) { 64 | slots[index].ref = ref; 65 | } 66 | 67 | public Zobject getRef(int index) { 68 | return slots[index].ref; 69 | } 70 | 71 | public void setSlot(int index, Slot slot) { 72 | slots[index] = slot; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Java/src/runtimedata/Zframe.java: -------------------------------------------------------------------------------- 1 | package runtimedata; 2 | 3 | import classfile.attribute.CodeAttribute; 4 | import runtimedata.heap.Zmethod; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/4 0004. 9 | * Desc:栈帧,执行方法所需的局部变量表大小和操作数栈深度是由编译器预先计算好的,存储在class文件method_info结构的Code属性中 10 | * 详细实现参考 {@link CodeAttribute} 11 | */ 12 | public class Zframe { 13 | Zframe lower; //当前帧的 前一帧的引用;相当于单向链表的前一个指针 14 | LocalVars localVars; //局部变量表的引用; 15 | OperandStack operandStack; //操作数栈的引用; 16 | Zthread thread; //当前栈帧所在的线程; 17 | Zmethod method; 18 | int nextPC; //frame中并不改变PC的值,其PC值是由ByteReader读取字节码不断改变的 19 | 20 | public Zframe(Zthread thread, int maxLocals, int maxStack) { 21 | this.thread = thread; 22 | localVars = new LocalVars(maxLocals); 23 | operandStack = new OperandStack(maxStack); 24 | } 25 | 26 | public Zframe(Zthread thread, Zmethod method) { 27 | this.thread = thread; 28 | this.method = method; 29 | localVars = new LocalVars(method.getMaxLocals()); 30 | operandStack = new OperandStack(method.getMaxStack()); 31 | } 32 | 33 | public LocalVars getLocalVars() { 34 | return localVars; 35 | } 36 | 37 | public OperandStack getOperandStack() { 38 | return operandStack; 39 | } 40 | 41 | public Zthread getThread() { 42 | return thread; 43 | } 44 | 45 | public int getNextPC() { 46 | return nextPC; 47 | } 48 | 49 | public void setNextPC(int nextPC) { 50 | this.nextPC = nextPC; 51 | } 52 | 53 | public Zmethod getMethod() { 54 | return method; 55 | } 56 | 57 | public void setMethod(Zmethod method) { 58 | this.method = method; 59 | } 60 | 61 | //用在new,getStatic,invokeStatic 等指令中,判断clinit 方法是否执行,如果执行,则需要保存当前thread 的 pc 62 | //eg:当前执行的是 new 指令,那么 thead 的 pc 指向的是 new, 63 | //再 push 一个新栈去执行,等直接结束后,在回到当前 frame,拿到 pc,此时的 pc 指向的还是 new 64 | //重新执行一遍 new 65 | public void revertNextPC() { 66 | this.nextPC = thread.getPc(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Java/src/runtimedata/Zstack.java: -------------------------------------------------------------------------------- 1 | package runtimedata; 2 | 3 | import java.util.EmptyStackException; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/4 0004. 8 | * Desc: 并没有采用数组的形式来保存栈帧,而是使用单向链表的形式,Zframe中保存这前一个帧的引用; 9 | * 最多持有1024个栈帧,当然这个值可以设置; 10 | */ 11 | public class Zstack { 12 | int maxSize; //虚拟机栈中所包含栈帧的最大容量 13 | int size; //当前虚拟机栈中包含帧的数量 14 | private Zframe _top; //栈顶的帧 15 | 16 | public Zstack(int maxSize) { 17 | this.maxSize = maxSize; 18 | } 19 | 20 | 21 | //新添加一个栈帧,将这个栈帧设置为top,当然如果当前栈之前有元素,那么将要push进的frame的lower是指为之前的top,当前frame变为top; 22 | void push(Zframe frame) { 23 | if (size > maxSize) { 24 | //throw new RuntimeException("java.lang.StackOverflowError"); 25 | //如果栈已经满了,按照Java虚拟机规范,应该抛出StackOverflowError异常 26 | throw new StackOverflowError(); 27 | } 28 | if (_top != null) { 29 | frame.lower = _top; // frame中保存前一个帧的引用,使得当前帧被push的时,前一个帧顶上去; 30 | } 31 | 32 | _top = frame; 33 | size++; 34 | } 35 | 36 | Zframe pop() { 37 | if (_top == null) { 38 | throw new EmptyStackException(); 39 | } 40 | Zframe tmp = _top; 41 | _top = tmp.lower; 42 | tmp.lower = null; //tmp是带pop出的栈帧,既然要pop出来,那么将其lower设置为null,不在持有栈中的帧,避免内存泄露; 43 | size--; 44 | return tmp; 45 | } 46 | 47 | Zframe top() { 48 | if (_top == null) { 49 | throw new EmptyStackException(); 50 | } 51 | return _top; 52 | } 53 | 54 | 55 | Zframe[] getFrames() { 56 | Zframe[] frames = new Zframe[size]; 57 | int i = 0; 58 | for (Zframe frame = _top;frame!=null;frame = frame.lower) { 59 | frames[i] = frame; 60 | i++; 61 | } 62 | return frames; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Java/src/runtimedata/Zthread.java: -------------------------------------------------------------------------------- 1 | package runtimedata; 2 | 3 | import runtimedata.heap.Zmethod; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/5/4 0004. 8 | * Desc: 定义Thread结构体,目前只定义了pc和stack两个字段,每个线程中都持有一个虚拟机栈的引用 9 | * Java虚拟机规范对Java虚拟机栈的约束也相当宽松, 10 | * 虚拟机栈可以是连续的空间,也可以不连续 11 | * 可以是固定大小,也可以在运行时动态扩展 12 | *

13 | * 如果Java虚拟机栈有大小限制,且执行线程所需的栈空间超出了这个限制,会导致StackOverflowError异常抛出。 14 | * 如果Java虚拟机栈可以动态扩展,但是内存已经耗尽,会导致OutOfMemoryError异常抛出。 15 | *

16 | * 其实Java命令提供了-Xss选项来设置Java虚拟机栈大小 17 | */ 18 | public class Zthread { 19 | private int pc; //该PC也不是自己修改的,而是由外部传入供当前线程所持有的; 20 | private Zstack stack; //Stack结构体(Java虚拟机栈)的引用; 21 | 22 | public Zthread() { 23 | //默认栈的大小是1024,也就是说可以存放1024个栈帧 24 | stack = new Zstack(1024); 25 | } 26 | 27 | public int getPc() { 28 | return pc; 29 | } 30 | 31 | public void setPc(int pc) { 32 | this.pc = pc; 33 | } 34 | 35 | public void pushFrame(Zframe frame) { 36 | stack.push(frame); 37 | } 38 | 39 | public Zframe popFrame() { 40 | return stack.pop(); 41 | } 42 | 43 | public Zframe getCurrentFrame() { 44 | return stack.top(); 45 | } 46 | 47 | public Zframe createFrame(int maxLocals, int maxStack) { 48 | return new Zframe(this, maxLocals, maxStack); 49 | } 50 | 51 | public Zframe createFrame(Zmethod method) { 52 | return new Zframe(this, method); 53 | } 54 | 55 | public boolean isStackEmpty() { 56 | return stack.size == 0; 57 | } 58 | 59 | public void clearStack() { 60 | while (!isStackEmpty()) { 61 | stack.pop(); 62 | } 63 | } 64 | 65 | public Zframe[] getFrames() { 66 | return stack.getFrames(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/AccessFlag.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/19 0019. 6 | * Desc: 访问标示,对于类,方法,字段,都有自己的访问标示; 7 | * 这里进行统一的封装,以后类,方法,字段的访问标识都从这个类取 8 | */ 9 | public class AccessFlag { 10 | public static final int ACC_PUBLIC = 0x0001; // class field method 11 | public static final int ACC_PRIVATE = 0x0002; // field method 12 | public static final int ACC_PROTECTED = 0x0004; // field method 13 | public static final int ACC_STATIC = 0x0008; // field method 14 | public static final int ACC_FINAL = 0x0010; // class field method 15 | public static final int ACC_SUPER = 0x0020; // class 16 | public static final int ACC_SYNCHRONIZED = 0x0020; // method 17 | public static final int ACC_VOLATILE = 0x0040; // field 18 | public static final int ACC_BRIDGE = 0x0040; // method 19 | public static final int ACC_TRANSIENT = 0x0080; // field 20 | public static final int ACC_VARARGS = 0x0080; // method 21 | public static final int ACC_NATIVE = 0x0100; // method 22 | public static final int ACC_INTERFACE = 0x0200; // class 23 | public static final int ACC_ABSTRACT = 0x0400; // class method 24 | public static final int ACC_STRICT = 0x0800; // method 25 | public static final int ACC_SYNTHETIC = 0x1000; // class field method 26 | public static final int ACC_ANNOTATION = 0x2000; // class 27 | public static final int ACC_ENUM = 0x4000; // class field 28 | } 29 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/ClassRef.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.classconstant.ConstantClassInfo; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/7/22. 8 | * Desc: 类引用 9 | */ 10 | public class ClassRef extends SymRef { 11 | public ClassRef(RuntimeConstantPool runtimeConstantPool, ConstantClassInfo classInfo) { 12 | super(runtimeConstantPool); 13 | this.className = classInfo.getName(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/ExceptionTable.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.attribute.CodeAttribute; 4 | 5 | /** 6 | * @author zachaxy 7 | * @date 18/1/2 8 | */ 9 | public class ExceptionTable { 10 | private ExceptionHandler[] exceptionTable; 11 | 12 | public ExceptionTable(CodeAttribute.ExceptionTableEntry[] entry, RuntimeConstantPool runtimeConstantPool) { 13 | exceptionTable = new ExceptionHandler[entry.length]; 14 | for (int i = 0; i < entry.length; i++) { 15 | exceptionTable[i] = new ExceptionHandler(); 16 | exceptionTable[i].startPc = entry[i].getStartPc(); 17 | exceptionTable[i].endPc = entry[i].getEndPc(); 18 | exceptionTable[i].handlerPc = entry[i].getHandlerPc(); 19 | exceptionTable[i].catchType = getCatchType(entry[i].getCatchType(), runtimeConstantPool); 20 | } 21 | } 22 | 23 | //将classFile中的异常类型(符号引用)转换为运行时的直接引用 24 | public ClassRef getCatchType(int index, RuntimeConstantPool runtimeConstantPool) { 25 | if (index == 0) { 26 | // catch all 27 | return null; 28 | } 29 | return (ClassRef) runtimeConstantPool.getRuntimeConstant(index).getValue(); 30 | } 31 | 32 | //返回能解决当前Exception的handler=>多个catch块,决定用哪个 33 | public ExceptionHandler findExceptionHandler(Zclass exClazz, int pc) { 34 | for (int i = 0; i < exceptionTable.length; i++) { 35 | ExceptionHandler handler = exceptionTable[i]; 36 | if (pc >= handler.startPc && pc < handler.endPc) { 37 | // catch all 38 | if (handler.catchType == null) { 39 | return handler; 40 | } 41 | // 如果catch 的异常是实际抛出的异常的父类,也可以捕获 42 | Zclass catchClazz = handler.catchType.resolvedClass(); 43 | if (catchClazz == exClazz || catchClazz.isSuperClassOf(exClazz)) { 44 | return handler; 45 | } 46 | } 47 | } 48 | return null; 49 | } 50 | } 51 | 52 | class ExceptionHandler { 53 | int startPc; 54 | int endPc; 55 | int handlerPc; 56 | ClassRef catchType; 57 | } -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/FieldRef.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.classconstant.ConstantFieldRefInfo; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/7/22 8 | * Desc: 字段引用 9 | */ 10 | public class FieldRef extends MemberRef { 11 | Zfield field; 12 | 13 | public FieldRef(RuntimeConstantPool runtimeConstantPool, ConstantFieldRefInfo fieldRefInfo) { 14 | super(runtimeConstantPool); 15 | copyMemberRefInfo(fieldRefInfo); 16 | } 17 | 18 | //字段引用转直接引用 19 | public Zfield resolvedField() { 20 | if (field == null) { 21 | resolvedRefField(); 22 | } 23 | 24 | return field; 25 | } 26 | 27 | public void resolvedRefField() { 28 | Zclass d = runtimeConstantPool.clazz; 29 | // 获取 fieldRef 所在的类 30 | Zclass c = resolvedClass(); 31 | //在该类中找到对应的字段 field 32 | Zfield field = lookupField(c, name, descriptor); 33 | if (field == null) { 34 | throw new NoSuchFieldError("NoSuchFieldError:" + name); 35 | } 36 | 37 | if (!field.isAccessTo(d)) { 38 | throw new IllegalAccessError(d.thisClassName + " can't access " + name + "in Class " + c.thisClassName); 39 | } 40 | 41 | this.field = field; 42 | } 43 | 44 | private Zfield lookupField(Zclass c, String name, String descriptor) { 45 | for (Zfield zf : c.fileds) { 46 | if (zf.name.equals(name) && zf.getDescriptor().equals(descriptor)) { 47 | return zf; 48 | } 49 | } 50 | 51 | for (Zclass zin : c.interfaces) { 52 | return lookupField(zin, name, descriptor); 53 | } 54 | 55 | if (c.superClass != null) { 56 | return lookupField(c.superClass, name, descriptor); 57 | } 58 | 59 | return null; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/InterfaceMethodRef.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.classconstant.ConstantInterfaceMethodRefInfo; 4 | 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/7/22. 9 | * Desc:接口方法引用 10 | */ 11 | public class InterfaceMethodRef extends MemberRef { 12 | Zmethod method; 13 | 14 | public InterfaceMethodRef(RuntimeConstantPool runtimeConstantPool, ConstantInterfaceMethodRefInfo interfaceMethodRefInfo) { 15 | super(runtimeConstantPool); 16 | copyMemberRefInfo(interfaceMethodRefInfo); 17 | } 18 | 19 | //接口方法引用转直接引用 20 | public Zmethod resolvedInterfaceMethod() { 21 | if (method == null) { 22 | resolveInterfaceMethodRef(); 23 | } 24 | return method; 25 | } 26 | 27 | private void resolveInterfaceMethodRef() { 28 | Zclass d = runtimeConstantPool.clazz; 29 | //获取 methodRef 所在的接口 30 | Zclass c = resolvedClass(); 31 | if (!c.isInterface()) { 32 | throw new IncompatibleClassChangeError(c.thisClassName); 33 | } 34 | //在该类中找到对应的方法 35 | Zmethod method = lookupInterfaceMethod(c, name, descriptor); 36 | if (method == null) { 37 | throw new NoSuchMethodError("NoSuchMethodError:" + name); 38 | } 39 | 40 | if (!method.isAccessTo(d)) { 41 | throw new IllegalAccessError(d.thisClassName + " can't access " + name + "in Class " + c.thisClassName); 42 | } 43 | 44 | this.method = method; 45 | } 46 | 47 | private Zmethod lookupInterfaceMethod(Zclass iface, String name, String descriptor) { 48 | for (Zmethod method : iface.methods) { 49 | if (method.name.equals(name) && method.descriptor.equals(descriptor)) { 50 | return method; 51 | } 52 | } 53 | return MethodLookup.lookupMethodInInterfaces(iface.interfaces, name, descriptor); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/MemberRef.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.classconstant.ConstantMemberRefInfo; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/7/22. 8 | * Desc: 字段和方法的符号引用保存的相同信息;包含全限名和描述符; 9 | * 字段和方法特有的属性,有其对应子类来实现; 10 | */ 11 | public class MemberRef extends SymRef { 12 | protected String name; //字段或方法名 13 | protected String descriptor; //字段或方法描述符 14 | 15 | public MemberRef(RuntimeConstantPool runtimeConstantPool) { 16 | super(runtimeConstantPool); 17 | } 18 | 19 | void copyMemberRefInfo(ConstantMemberRefInfo refInfo) { 20 | className = refInfo.getClassName(); 21 | name = refInfo.getName(); 22 | descriptor = refInfo.getDescriptor(); 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public String getDescriptor() { 30 | return descriptor; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/MethodLookup.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | /** 4 | * @author zachaxy 5 | * @date 17/12/25 6 | */ 7 | public class MethodLookup { 8 | public static Zmethod lookupMethodInClass(Zclass clazz, String name, String descriptor) { 9 | Zclass c = clazz; 10 | while (c != null) { 11 | for (Zmethod method : c.methods) { 12 | if (method.name.equals(name) && method.descriptor.equals(descriptor)) { 13 | return method; 14 | } 15 | } 16 | c = c.superClass; 17 | } 18 | return null; 19 | } 20 | 21 | public static Zmethod lookupMethodInInterfaces(Zclass[] ifaces, String name, String descriptor) { 22 | for (Zclass iface : ifaces) { 23 | for (Zmethod method : iface.methods) { 24 | if (method.name.equals(name) && method.descriptor.equals(descriptor)) { 25 | return method; 26 | } 27 | } 28 | Zmethod method = lookupMethodInInterfaces(iface.interfaces, name, descriptor); 29 | if (method != null) { 30 | return method; 31 | } 32 | } 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/MethodRef.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.classconstant.ConstantMethodRefInfo; 4 | 5 | /** 6 | * Author: zhangxin 7 | * Time: 2017/7/22. 8 | * Desc: 非接口方法引用; 9 | */ 10 | public class MethodRef extends MemberRef { 11 | Zmethod method; 12 | 13 | public MethodRef(RuntimeConstantPool runtimeConstantPool, ConstantMethodRefInfo methodRefInfo) { 14 | super(runtimeConstantPool); 15 | copyMemberRefInfo(methodRefInfo); 16 | } 17 | 18 | //非接口方法引用转直接引用 19 | public Zmethod resolvedMethod() { 20 | if (method == null) { 21 | resolvedRefMethod(); 22 | } 23 | 24 | return method; 25 | } 26 | 27 | public void resolvedRefMethod() { 28 | Zclass d = runtimeConstantPool.clazz; 29 | //获取 methodRef 所在的类 30 | Zclass c = resolvedClass(); 31 | if (c.isInterface()) { 32 | throw new IncompatibleClassChangeError(c.thisClassName); 33 | } 34 | //在该类中找到对应的方法 35 | Zmethod method = lookupMethod(c, name, descriptor); 36 | if (method == null) { 37 | throw new NoSuchMethodError("NoSuchMethodError:" + name); 38 | } 39 | 40 | if (!method.isAccessTo(d)) { 41 | throw new IllegalAccessError(d.thisClassName + " can't access " + name + "in Class " + c.thisClassName); 42 | } 43 | 44 | this.method = method; 45 | } 46 | 47 | //TODO:需验证方法引用,在父类找不到后,是否需要从其接口中再去找? 48 | private Zmethod lookupMethod(Zclass c, String name, String descriptor) { 49 | return MethodLookup.lookupMethodInClass(c, name, descriptor); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/RuntimeConstantInfo.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | /** 4 | * @author zachaxy 5 | * @date 17/12/25 6 | * desc:运行时常量,区别于 class 文件中的常量 7 | * 本想用泛型来约束运行时常量池的类型,这样在取运行时常量池的值时可以避免丑陋的类型强壮代码风格 8 | * 无奈的是,运行时常量池是放在数组中的,一旦放入数组,其对象的泛型类型也就消失了 9 | * 所以使用标志位 type 来识别类型,取出后再进行类型转换 10 | */ 11 | public class RuntimeConstantInfo { 12 | private T value; 13 | private int type; 14 | 15 | RuntimeConstantInfo(T value,int type){ 16 | this.value = value; 17 | this.type = type; 18 | } 19 | 20 | public T getValue(){ 21 | return value; 22 | } 23 | 24 | public int getType() { 25 | return type; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/StringPool.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @author zachaxy 7 | * @date 17/12/30 8 | * desc:这里用来模拟 JVM 中的字符串池,但是由于当前的 JVM 本身就是用 Java 写的,所以会省掉很多真正的细节 9 | * 这里用一个 HasMap 来模拟字符串池,key 为从 class 文件中读到的字符串,value 为我们定义的 Zobject 10 | */ 11 | public class StringPool { 12 | public static HashMap internedStrings = new HashMap<>(); 13 | public static HashMap realInternedStrings = new HashMap<>(); 14 | 15 | public static Zobject jString(ZclassLoader loader, String str) { 16 | if (internedStrings.containsKey(str)) { 17 | return internedStrings.get(str); 18 | } 19 | 20 | // chars := stringToUtf16(goStr) 21 | // jChars := &Object{loader.LoadClass("[C"), chars, nil} 22 | // 23 | // //这里创建了一个String的对象 24 | // jStr := loader.LoadClass("java/lang/String").NewObject() 25 | // //不是通过构造方法,而是通过直接setVar的方式,将上面创建的jChar数组设置进来; 26 | // jStr.SetRefVar("value", "[C", jChars) 27 | // 28 | // internedStrings[goStr] = jStr 29 | // return jStr 30 | char[] chars = str.toCharArray(); 31 | Zobject jChars = new Zobject(loader.loadClass("[C"), chars, null); 32 | 33 | Zobject jStr = loader.loadClass("java/lang/String").newObject(); 34 | jStr.setRefVar("value", "[C", jChars); 35 | internedStrings.put(str, jStr); 36 | //这一步的实现有些取巧了,Zobject 并没有实现 equals 和 hashCode 方法,但依然可以作为 key 37 | //是因为在 internedStrings 中的 key 是 java 中的String,这是合法的,相同的 String 取到的 value 38 | //也就是 Zobject ,也是一样的;这就保证了 Zobject 可以作为hashMap 的 key; 39 | realInternedStrings.put(jStr, str); 40 | return jStr; 41 | } 42 | 43 | //凡是调用该方法,必定是从上面的常量池中获取了相同的字符串,然后返回其在 JVM 中的 Zobject 44 | public static String realString(Zobject jStr) { 45 | if (realInternedStrings.containsKey(jStr)) { 46 | return realInternedStrings.get(jStr); 47 | } 48 | 49 | Zobject ref = jStr.getRefVar("value", "[C"); 50 | char[] chars = ref.getChars(); 51 | String realStr = new String(chars); 52 | realInternedStrings.put(jStr, realStr); 53 | return realStr; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/SymRef.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | /** 4 | * Author: zhangxin 5 | * Time: 2017/5/24 0024. 6 | * Desc: 保存符号引用的一些共有属性; 7 | * 这里一个重要的工作是将被引用的类的class加载进来; 8 | */ 9 | public class SymRef { 10 | RuntimeConstantPool runtimeConstantPool; //存放符号引用所在的运行时常量池指针,可以通过符号引用访问到运行时常量池,进一步又可以访问到类数据 11 | String className; //存放类的完全限定名 12 | Zclass clazz; //上述运行时常量池的宿主类中的符号引用的真正类,在外面访问时,根据 clazz 是否为 null 来决定是否执行 loadClass 13 | 14 | public SymRef(RuntimeConstantPool runtimeConstantPool) { 15 | this.runtimeConstantPool = runtimeConstantPool; 16 | } 17 | 18 | //类引用转直接引用 19 | public Zclass resolvedClass() { 20 | if (clazz == null) { 21 | resolvedClassRef(); 22 | } 23 | return clazz; 24 | } 25 | 26 | // 当前类(cp的宿主类)d中,如果引用了类c,那么就将c加载进来 27 | private void resolvedClassRef() { 28 | Zclass d = runtimeConstantPool.clazz; 29 | Zclass c = d.loader.loadClass(className); 30 | //在这里判断下 d 能否访问 c 31 | if (!c.isAccessibleTo(d)) { 32 | throw new IllegalAccessError(d.thisClassName + " can't access " + c.thisClassName); 33 | } 34 | clazz = c; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Java/src/runtimedata/heap/Zfield.java: -------------------------------------------------------------------------------- 1 | package runtimedata.heap; 2 | 3 | import classfile.attribute.ConstantValueAttribute; 4 | import classfile.MemberInfo; 5 | 6 | /** 7 | * Author: zhangxin 8 | * Time: 2017/5/19 0019. 9 | * Desc: 字段的抽象,是在class中定义的字段,包括静态的和非静态的 10 | */ 11 | public class Zfield extends ClassMember { 12 | //运行时常量池中的索引,该属性只有在static final成员有初值的情况下才有; 13 | int constValueIndex; 14 | //类中字段数组slots中的的索引;其赋值在首次加载 class 文件后,为其分配的 slotId 15 | //如果是静态字段,该 slotId 表示的是在 Class 中staticVars数组中的索引 16 | //如果是非静态字段,该 slotId 表示的是在 Object 中 fields 数组中的索引 17 | int slotId; 18 | 19 | private Zfield(Zclass clazz, MemberInfo classFileField) { 20 | super(clazz, classFileField); 21 | copyAttributes(classFileField); 22 | } 23 | 24 | 25 | public static Zfield[] makeFields(Zclass zclass, MemberInfo[] cfFields) { 26 | Zfield[] fields = new Zfield[cfFields.length]; 27 | for (int i = 0; i < fields.length; i++) { 28 | Zfield field = new Zfield(zclass, cfFields[i]); 29 | fields[i] = field; 30 | } 31 | return fields; 32 | } 33 | 34 | 35 | public void copyAttributes(MemberInfo classFileField) { 36 | ConstantValueAttribute constantValueAttribute = classFileField.getConstantValueAttribute(); 37 | if (constantValueAttribute != null) { 38 | constValueIndex = constantValueAttribute.getConstantValueIndex(); 39 | } 40 | } 41 | 42 | public boolean isVolatile() { 43 | return 0 != (accessFlags & AccessFlag.ACC_VOLATILE); 44 | } 45 | 46 | public boolean isTransient() { 47 | return 0 != (accessFlags & AccessFlag.ACC_TRANSIENT); 48 | } 49 | 50 | public boolean isEnum() { 51 | return 0 != (accessFlags & AccessFlag.ACC_ENUM); 52 | } 53 | 54 | 55 | public int getConstValueIndex() { 56 | return constValueIndex; 57 | } 58 | 59 | public int getSlotId() { 60 | return slotId; 61 | } 62 | 63 | public boolean isLongOrDouble() { 64 | return getDescriptor().equals("J") || getDescriptor().equals("D"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Java/src/test/TestCmd01.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import Utils.Cmd; 4 | 5 | import java.util.Scanner; 6 | 7 | /** 8 | * @author zhangxin 9 | * @date 2017/12/22 0022 10 | */ 11 | public class TestCmd01 { 12 | public static void main(String[] args) { 13 | System.out.println("Usage: java [-options] class [args...]"); 14 | System.out.println("Specially,we don't support the path that contains space!"); 15 | 16 | Scanner in = new Scanner(System.in); 17 | String cmdLine = in.nextLine(); 18 | String[] cmds = cmdLine.split("\\s+"); 19 | Cmd cmd = new Cmd(cmds); 20 | if (!cmd.isRightFmt()) { 21 | System.out.println("Unrecognized command!"); 22 | cmd.printUsage(); 23 | } else if(!cmd.isRightOpt()){ 24 | System.out.println("Unrecognized option: "+cmds[1]); 25 | cmd.printUsage(); 26 | }else { 27 | if (cmd.isVersionFlag()) { 28 | System.out.println("java version \"1.8.0_20\"\n" 29 | + "Java(TM) SE Runtime Environment (build 1.8.0_20-b26)\n" 30 | + "Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)"); 31 | } else if (cmd.isHelpFlag()) { 32 | cmd.printUsage(); 33 | } else { 34 | System.out.println("cmd pared successful!"); 35 | for (int i = 0; i < cmd.getArgs().length; i++) { 36 | System.out.println(cmd.getArgs()[i]); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Java/src/test/TestLocalVars04.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import runtimedata.LocalVars; 4 | 5 | /** 6 | * @author zachaxy 7 | * @date 17/12/24 8 | */ 9 | public class TestLocalVars04 { 10 | 11 | public static void main(String[] args) { 12 | LocalVars localVars = new LocalVars(10); 13 | localVars.setInt(0,100); 14 | localVars.setInt(1,-100); 15 | localVars.setLong(2,2997934580L); 16 | localVars.setLong(4,-2997934580L); 17 | localVars.setFloat(6,3.1415926f); 18 | localVars.setDouble(7,2.141592678912); 19 | System.out.println(localVars.getInt(0)); 20 | System.out.println(localVars.getInt(1)); 21 | System.out.println(localVars.getLong(2)); 22 | System.out.println(localVars.getLong(4)); 23 | System.out.println(localVars.getFloat(6)); 24 | System.out.println(localVars.getDouble(7)); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Java/src/test/TestOperandStack05.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import runtimedata.OperandStack; 4 | 5 | /** 6 | * @author zachaxy 7 | * @date 17/12/24 8 | */ 9 | public class TestOperandStack05 { 10 | public static void main(String[] args) { 11 | OperandStack stack = new OperandStack(10); 12 | stack.pushInt(100); 13 | stack.pushInt(-100); 14 | stack.pushLong(2997934580L); 15 | stack.pushLong(-2997934580L); 16 | stack.pushFloat(3.1415925f); 17 | stack.pushDouble(2.141592678912); 18 | 19 | System.out.println(stack.popDouble()); 20 | System.out.println(stack.popFloat()); 21 | System.out.println(stack.popLong()); 22 | System.out.println(stack.popLong()); 23 | System.out.println(stack.popInt()); 24 | System.out.println(stack.popInt()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Java/src/znative/NativeMethod.java: -------------------------------------------------------------------------------- 1 | package znative; 2 | 3 | import runtimedata.Zframe; 4 | 5 | /** 6 | * @author zachaxy 7 | * @date 17/12/31 8 | * native native方法统一实现的接口 9 | */ 10 | public interface NativeMethod { 11 | public void run(Zframe frame); 12 | } 13 | -------------------------------------------------------------------------------- /Java/src/znative/java/lang/NStackTraceElement.java: -------------------------------------------------------------------------------- 1 | package znative.java.lang; 2 | 3 | /** 4 | * @author zachaxy 5 | * @date 18/1/3 6 | * desc:虚拟机栈信息 7 | */ 8 | 9 | public class NStackTraceElement { 10 | String fileName;//类所在的java文件 11 | String className;//声明方法的类名 12 | String methodName;//调用方法名 13 | int lineNumber;//出现exception的行号 14 | 15 | public NStackTraceElement(String fileName, String className, String methodName, int lineNumber) { 16 | this.fileName = fileName; 17 | this.className = className; 18 | this.methodName = methodName; 19 | this.lineNumber = lineNumber; 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | return className + "." + methodName + "(" + fileName + ":" + lineNumber + ")"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Java/src/znative/java/lang/Nclass.java: -------------------------------------------------------------------------------- 1 | package znative.java.lang; 2 | 3 | import runtimedata.Zframe; 4 | import runtimedata.heap.StringPool; 5 | import runtimedata.heap.Zclass; 6 | import runtimedata.heap.ZclassLoader; 7 | import runtimedata.heap.Zobject; 8 | import znative.NativeMethod; 9 | 10 | /** 11 | * @author zachaxy 12 | * @date 18/1/2 13 | */ 14 | public class Nclass { 15 | 16 | // static native Class getPrimitiveClass(String name); 17 | // (Ljava/lang/String;)Ljava/lang/Class; 18 | // 该方法是获取基本类型的类对象; 19 | public static class getPrimitiveClass implements NativeMethod { 20 | @Override 21 | public void run(Zframe frame) { 22 | Zobject nameObj = frame.getLocalVars().getRef(0); 23 | String name = StringPool.realString(nameObj); 24 | ZclassLoader classLoader = frame.getMethod().getClazz().getLoader(); 25 | Zobject jObject = classLoader.loadClass(name).getjObject(); 26 | frame.getOperandStack().pushRef(jObject); 27 | } 28 | } 29 | 30 | public static class getName0 implements NativeMethod { 31 | @Override 32 | public void run(Zframe frame) { 33 | Zobject self = frame.getLocalVars().getRef(0); 34 | Zclass clazz = (Zclass) self.extra; 35 | String name = clazz.getJavaName(); 36 | Zobject nameObj = StringPool.jString(clazz.getLoader(), name); 37 | frame.getOperandStack().pushRef(nameObj); 38 | } 39 | } 40 | 41 | public static class desiredAssertionStatus0 implements NativeMethod { 42 | @Override 43 | public void run(Zframe frame) { 44 | frame.getOperandStack().pushBoolean(false); 45 | } 46 | } 47 | 48 | public static class isArray implements NativeMethod { 49 | @Override 50 | public void run(Zframe frame) { 51 | Zobject self = frame.getLocalVars().getRef(0); 52 | Zclass clazz = (Zclass) self.extra; 53 | frame.getOperandStack().pushBoolean(clazz.isArray()); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /Java/src/znative/java/lang/Nobject.java: -------------------------------------------------------------------------------- 1 | package znative.java.lang; 2 | 3 | 4 | import runtimedata.Zframe; 5 | import runtimedata.heap.Zobject; 6 | import znative.NativeMethod; 7 | 8 | /** 9 | * @author zachaxy 10 | * @date 18/1/2 11 | */ 12 | 13 | 14 | public class Nobject { 15 | // static native Class getPrimitiveClass(String name); 16 | // (Ljava/lang/String;)Ljava/lang/Class; 17 | //该方法是获取非基本类型的类对象; 18 | public static class getClass implements NativeMethod { 19 | 20 | @Override 21 | public void run(Zframe frame) { 22 | // 从局部变量表中获取非静态方法的实际的第一个参数——this 23 | Zobject self = frame.getLocalVars().getRef(0); 24 | Zobject jObject = self.getClazz().getjObject(); 25 | frame.getOperandStack().pushRef(jObject); 26 | } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 本项目是用 Java 实现了一个简易版本的 Java 虚拟机 ,重点在于了解 Java 虚拟机内部的工作原理。开发过程中的具体细节及所遇到的问题,都记录在我的博客[手写JVM系列](https://zachaxy.github.io/tags/JVM/)中。 2 | 3 | 4 | --------------------------------------------------------------------------------