From 74b0140f85c5fe31da7b4513a2de548b3ad8b0e9 Mon Sep 17 00:00:00 2001 From: wangxiang Date: Wed, 25 Oct 2023 17:05:22 +0800 Subject: [PATCH] update --- src/main/java/haidnor/jvm/HaidnorJVM.java | 11 +- .../haidnor/jvm/bcel/classfile/Constant.java | 5 + .../jvm/bcel/classfile/ConstantMethodref.java | 43 + .../jvm/bcel/classfile/ConstantPool.java | 3 + .../haidnor/jvm/bcel/classfile/JavaClass.java | 15 + .../haidnor/jvm/core/JavaExecutionEngine.java | 6 +- .../jvm/instruction/InstructionFactory.java | 1217 +++++++++-------- .../jvm/instruction/comparisons/DCMPG.java | 31 + .../jvm/instruction/comparisons/DCMPL.java | 31 + .../jvm/instruction/comparisons/FCMPG.java | 30 + .../jvm/instruction/comparisons/FCMPL.java | 30 + .../jvm/instruction/comparisons/IFEQ.java | 40 + .../jvm/instruction/comparisons/IFGE.java | 34 + .../jvm/instruction/comparisons/IFGT.java | 34 + .../jvm/instruction/comparisons/IFLE.java | 34 + .../jvm/instruction/comparisons/IFLT.java | 34 + .../jvm/instruction/comparisons/IFNE.java | 43 + .../instruction/comparisons/IF_ACMPEQ.java | 36 + .../instruction/comparisons/IF_ACMPNE.java | 36 + .../instruction/comparisons/IF_ICMPEQ.java | 42 + .../instruction/comparisons/IF_ICMPGE.java | 42 + .../instruction/comparisons/IF_ICMPGT.java | 42 + .../instruction/comparisons/IF_ICMPLE.java | 37 + .../instruction/comparisons/IF_ICMPLT.java | 42 + .../instruction/comparisons/IF_ICMPNE.java | 42 + .../jvm/instruction/comparisons/LCMP.java | 28 + .../instruction/constants/ACONST_NULL.java | 20 + .../jvm/instruction/constants/BIPUSH.java | 29 + .../jvm/instruction/constants/DCONST_0.java | 26 + .../jvm/instruction/constants/DCONST_1.java | 26 + .../jvm/instruction/constants/FCONST_1.java | 26 + .../jvm/instruction/constants/FCONST_2.java | 26 + .../jvm/instruction/constants/ICONST_0.java | 23 + .../jvm/instruction/constants/ICONST_1.java | 23 + .../jvm/instruction/constants/ICONST_2.java | 23 + .../jvm/instruction/constants/ICONST_3.java | 23 + .../jvm/instruction/constants/ICONST_4.java | 23 + .../jvm/instruction/constants/ICONST_5.java | 23 + .../jvm/instruction/constants/ICONST_M1.java | 23 + .../jvm/instruction/constants/LCONST_0.java | 26 + .../jvm/instruction/constants/LCONST_1.java | 26 + .../jvm/instruction/constants/LDC.java | 58 + .../jvm/instruction/constants/LDC2W.java | 48 + .../jvm/instruction/constants/LDC_W.java | 58 + .../jvm/instruction/constants/NOP.java | 23 + .../jvm/instruction/constants/SIPUSH.java | 29 + .../jvm/instruction/control/ARETURN.java | 25 + .../jvm/instruction/control/DRETURN.java | 25 + .../jvm/instruction/control/FRETURN.java | 25 + .../jvm/instruction/control/IRETURN.java | 25 + .../jvm/instruction/control/LOOKUPSWITCH.java | 19 + .../jvm/instruction/control/LRETURN.java | 25 + .../haidnor/jvm/instruction/control/RET.java | 28 + .../jvm/instruction/control/RETURN.java | 18 + .../{ => control}/ReturnableInstruction.java | 3 +- .../jvm/instruction/control/TABLESWITCH.java | 19 + .../jvm/instruction/conversions/D2F.java | 20 + .../jvm/instruction/conversions/D2I.java | 19 + .../jvm/instruction/conversions/D2L.java | 19 + .../jvm/instruction/conversions/F2D.java | 19 + .../jvm/instruction/conversions/F2I.java | 19 + .../jvm/instruction/conversions/F2L.java | 19 + .../jvm/instruction/conversions/I2B.java | 24 + .../jvm/instruction/conversions/I2C.java | 21 + .../jvm/instruction/conversions/I2D.java | 19 + .../jvm/instruction/conversions/I2F.java | 19 + .../jvm/instruction/conversions/I2L.java | 19 + .../jvm/instruction/conversions/I2S.java | 20 + .../jvm/instruction/conversions/L2D.java | 19 + .../jvm/instruction/conversions/L2F.java | 19 + .../jvm/instruction/conversions/L2I.java | 19 + .../jvm/instruction/extended/GOTO.java | 33 + .../jvm/instruction/extended/GOTO_W.java | 27 + .../jvm/instruction/extended/IFNONNULL.java | 33 + .../jvm/instruction/extended/IFNULL.java | 33 + .../instruction/extended/MULTIANEWARRAY.java | 25 + .../jvm/instruction/extended/WIDE.java | 40 + .../haidnor/jvm/instruction/loads/AALOAD.java | 24 + .../haidnor/jvm/instruction/loads/ALOAD.java | 25 + .../jvm/instruction/loads/ALOAD_0.java | 21 + .../jvm/instruction/loads/ALOAD_1.java | 21 + .../jvm/instruction/loads/ALOAD_2.java | 21 + .../jvm/instruction/loads/ALOAD_3.java | 21 + .../haidnor/jvm/instruction/loads/BALOAD.java | 22 + .../haidnor/jvm/instruction/loads/CALOAD.java | 22 + .../haidnor/jvm/instruction/loads/DALOAD.java | 22 + .../haidnor/jvm/instruction/loads/DLOAD.java | 25 + .../jvm/instruction/loads/DLOAD_0.java | 21 + .../jvm/instruction/loads/DLOAD_1.java | 21 + .../jvm/instruction/loads/DLOAD_2.java | 21 + .../jvm/instruction/loads/DLOAD_3.java | 21 + .../haidnor/jvm/instruction/loads/FALOAD.java | 22 + .../haidnor/jvm/instruction/loads/FLOAD.java | 25 + .../jvm/instruction/loads/FLOAD_0.java | 21 + .../jvm/instruction/loads/FLOAD_1.java | 21 + .../jvm/instruction/loads/FLOAD_2.java | 21 + .../jvm/instruction/loads/FLOAD_3.java | 21 + .../haidnor/jvm/instruction/loads/IALOAD.java | 22 + .../haidnor/jvm/instruction/loads/ILOAD.java | 25 + .../jvm/instruction/loads/ILOAD_0.java | 24 + .../jvm/instruction/loads/ILOAD_1.java | 24 + .../jvm/instruction/loads/ILOAD_2.java | 24 + .../jvm/instruction/loads/ILOAD_3.java | 24 + .../haidnor/jvm/instruction/loads/LALOAD.java | 22 + .../haidnor/jvm/instruction/loads/LLOAD.java | 25 + .../jvm/instruction/loads/LLOAD_0.java | 21 + .../jvm/instruction/loads/LLOAD_1.java | 21 + .../jvm/instruction/loads/LLOAD_2.java | 21 + .../jvm/instruction/loads/LLOAD_3.java | 21 + .../haidnor/jvm/instruction/loads/SALOAD.java | 22 + .../haidnor/jvm/instruction/math/DADD.java | 23 + .../haidnor/jvm/instruction/math/DDIV.java | 23 + .../haidnor/jvm/instruction/math/DMUL.java | 23 + .../haidnor/jvm/instruction/math/DNEG.java | 23 + .../haidnor/jvm/instruction/math/DREM.java | 23 + .../haidnor/jvm/instruction/math/DSUB.java | 23 + .../haidnor/jvm/instruction/math/FADD.java | 23 + .../haidnor/jvm/instruction/math/FDIV.java | 23 + .../haidnor/jvm/instruction/math/FMUL.java | 23 + .../haidnor/jvm/instruction/math/FNEG.java | 23 + .../haidnor/jvm/instruction/math/FREM.java | 23 + .../haidnor/jvm/instruction/math/FSUB.java | 23 + .../haidnor/jvm/instruction/math/IADD.java | 23 + .../haidnor/jvm/instruction/math/IAND.java | 21 + .../haidnor/jvm/instruction/math/IDIV.java | 23 + .../haidnor/jvm/instruction/math/IINC.java | 37 + .../haidnor/jvm/instruction/math/IMUL.java | 23 + .../haidnor/jvm/instruction/math/INEG.java | 23 + .../haidnor/jvm/instruction/math/IOR.java | 20 + .../haidnor/jvm/instruction/math/IREM.java | 23 + .../haidnor/jvm/instruction/math/ISHL.java | 22 + .../haidnor/jvm/instruction/math/ISHR.java | 22 + .../haidnor/jvm/instruction/math/ISUB.java | 23 + .../haidnor/jvm/instruction/math/IUSHR.java | 37 + .../haidnor/jvm/instruction/math/IXOR.java | 20 + .../haidnor/jvm/instruction/math/LADD.java | 23 + .../haidnor/jvm/instruction/math/LAND.java | 20 + .../haidnor/jvm/instruction/math/LDIV.java | 23 + .../haidnor/jvm/instruction/math/LMUL.java | 23 + .../haidnor/jvm/instruction/math/LNEG.java | 23 + .../haidnor/jvm/instruction/math/LOR.java | 20 + .../haidnor/jvm/instruction/math/LREM.java | 23 + .../haidnor/jvm/instruction/math/LSHL.java | 22 + .../haidnor/jvm/instruction/math/LSHR.java | 20 + .../haidnor/jvm/instruction/math/LSUB.java | 23 + .../haidnor/jvm/instruction/math/LUSHR.java | 28 + .../haidnor/jvm/instruction/math/LXOR.java | 20 + .../jvm/instruction/references/ANEWARRAY.java | 41 + .../instruction/references/ARRAYLENGTH.java | 22 + .../jvm/instruction/references/ATHROW.java | 22 + .../jvm/instruction/references/CHECKCAST.java | 24 + .../jvm/instruction/references/GETFIELD.java | 52 + .../jvm/instruction/references/GETSTATIC.java | 51 + .../instruction/references/INSTANCEOF.java | 78 ++ .../instruction/references/INVOKEDYNAMIC.java | 21 + .../references/INVOKEINTERFACE.java | 146 ++ .../instruction/references/INVOKESPECIAL.java | 78 ++ .../instruction/references/INVOKESTATIC.java | 91 ++ .../instruction/references/INVOKEVIRTUAL.java | 108 ++ .../jvm/instruction/references/JSR.java | 30 + .../jvm/instruction/references/JSR_W.java | 26 + .../instruction/references/MONITORENTER.java | 21 + .../instruction/references/MONITOREXIT.java | 21 + .../jvm/instruction/references/NEW.java | 44 + .../jvm/instruction/references/NEWARRAY.java | 53 + .../jvm/instruction/references/PUTFIELD.java | 36 + .../jvm/instruction/references/PUTSTATIC.java | 38 + .../haidnor/jvm/instruction/stack/DUP.java | 27 + .../haidnor/jvm/instruction/stack/DUP2.java | 41 + .../jvm/instruction/stack/DUP2_X1.java | 36 + .../jvm/instruction/stack/DUP2_X2.java | 70 + .../haidnor/jvm/instruction/stack/DUP_X1.java | 36 + .../haidnor/jvm/instruction/stack/DUP_X2.java | 47 + .../haidnor/jvm/instruction/stack/POP.java | 20 + .../haidnor/jvm/instruction/stack/POP2.java | 20 + .../haidnor/jvm/instruction/stack/SWAP.java | 24 + .../jvm/instruction/stores/AASTORE.java | 23 + .../jvm/instruction/stores/ASTORE.java | 23 + .../jvm/instruction/stores/ASTORE_0.java | 20 + .../jvm/instruction/stores/ASTORE_1.java | 20 + .../jvm/instruction/stores/ASTORE_2.java | 20 + .../jvm/instruction/stores/ASTORE_3.java | 20 + .../jvm/instruction/stores/BASTORE.java | 22 + .../jvm/instruction/stores/CASTORE.java | 22 + .../jvm/instruction/stores/DASTORE.java | 22 + .../jvm/instruction/stores/DSTORE.java | 23 + .../jvm/instruction/stores/DSTORE_0.java | 20 + .../jvm/instruction/stores/DSTORE_1.java | 20 + .../jvm/instruction/stores/DSTORE_2.java | 20 + .../jvm/instruction/stores/DSTORE_3.java | 20 + .../jvm/instruction/stores/FASTORE.java | 22 + .../jvm/instruction/stores/FSTORE.java | 23 + .../jvm/instruction/stores/FSTORE_0.java | 20 + .../jvm/instruction/stores/FSTORE_1.java | 20 + .../jvm/instruction/stores/FSTORE_2.java | 20 + .../jvm/instruction/stores/FSTORE_3.java | 20 + .../jvm/instruction/stores/IASTORE.java | 22 + .../jvm/instruction/stores/ISTORE.java | 23 + .../jvm/instruction/stores/ISTORE_0.java | 20 + .../jvm/instruction/stores/ISTORE_1.java | 20 + .../jvm/instruction/stores/ISTORE_2.java | 20 + .../jvm/instruction/stores/ISTORE_3.java | 20 + .../jvm/instruction/stores/LASTORE.java | 22 + .../jvm/instruction/stores/LSTORE.java | 23 + .../jvm/instruction/stores/LSTORE_0.java | 20 + .../jvm/instruction/stores/LSTORE_1.java | 20 + .../jvm/instruction/stores/LSTORE_2.java | 20 + .../jvm/instruction/stores/LSTORE_3.java | 20 + .../jvm/instruction/stores/SASTORE.java | 22 + src/main/java/haidnor/jvm/rtda/Instance.java | 8 +- src/main/java/haidnor/jvm/runtime/Frame.java | 3 - src/test/java/haidnor/jvm/Student.java | 6 - src/test/java/haidnor/jvm/SuperStudent.java | 6 - src/test/java/haidnor/jvm/test/BCELTest.java | 15 - src/test/java/haidnor/jvm/test/TestJVM.java | 173 +++ .../java/haidnor/jvm/test/clazz/Func.java | 7 + .../haidnor/jvm/test/clazz/HelloWorld.java | 8 + .../java/haidnor/jvm/test/clazz/Human.java | 16 + .../java/haidnor/jvm/test/clazz/Organism.java | 8 + .../haidnor/jvm/test/clazz/Organism0.java | 12 + .../java/haidnor/jvm/test/clazz/Student.java | 19 + .../haidnor/jvm/test/clazz/StudentEnum.java | 23 + .../java/haidnor/jvm/test/demo/Demo2.java | 12 + .../java/haidnor/jvm/test/demo/Demo3.java | 22 + .../java/haidnor/jvm/test/demo/Demo4.java | 12 + .../java/haidnor/jvm/test/demo/Demo5.java | 27 + .../java/haidnor/jvm/test/demo/Demo6.java | 16 + .../java/haidnor/jvm/test/demo/Demo7.java | 20 + .../java/haidnor/jvm/test/demo/Demo8.java | 17 + .../java/haidnor/jvm/test/demo/demo_add.java | 17 + .../haidnor/jvm/test/demo/demo_doWhile.java | 27 + .../haidnor/jvm/test/demo/demo_enum_1.java | 11 + .../jvm/test/demo/demo_exception_1.java | 37 + .../jvm/test/demo/demo_exception_2.java | 53 + .../jvm/test/demo/demo_exception_3.java | 50 + .../jvm/test/demo/demo_exception_4.java | 50 + .../haidnor/jvm/test/demo/demo_finally_1.java | 51 + .../haidnor/jvm/test/demo/demo_finally_2.java | 55 + .../haidnor/jvm/test/demo/demo_finally_3.java | 55 + .../java/haidnor/jvm/test/demo/demo_for.java | 31 + .../haidnor/jvm/test/demo/demo_foreach_1.java | 62 + .../haidnor/jvm/test/demo/demo_foreach_2.java | 25 + .../haidnor/jvm/test/demo/demo_foreach_3.java | 20 + .../jvm/test/demo/demo_helloWorld.java | 18 + .../haidnor/jvm/test/demo/demo_while.java | 29 + .../java/haidnor/jvm/test/demo1/Test1.java | 22 + .../haidnor/jvm/test/instruction/Array.java | 10 + .../haidnor/jvm/test/instruction/ClassA.java | 12 + .../jvm/test/instruction/DO_WHILE.java | 11 + .../haidnor/jvm/test/instruction/GOTO.java | 13 + .../jvm/test/instruction/InnerClass.java | 9 + .../jvm/test/instruction/loads/Person.java | 4 + .../jvm/test/instruction/loads/Student.java | 31 + .../jvm/test/instruction/loads/Student1.java | 13 + .../jvm/test/instruction/math/DADD.java | 15 + .../jvm/test/instruction/math/FADD.java | 15 + .../jvm/test/instruction/math/IADD.java | 15 + .../jvm/test/instruction/math/IINC.java | 23 + .../jvm/test/instruction/math/ISUB.java | 10 + .../jvm/test/instruction/math/LADD.java | 15 + .../jvm/test/instruction/math/LSUB.java | 10 + .../references/CallStaticMethod.java | 14 + .../jvm/test/instruction/references/NEW.java | 21 + .../java/haidnor/jvm/test/model/Animal.java | 5 + .../jvm/test/model/CustomClassLoader.java | 40 + .../java/haidnor/jvm/test/model/Demo.java | 29 + src/test/java/haidnor/jvm/test/model/Dog.java | 7 + .../java/haidnor/jvm/test/model/DogTest.java | 15 + .../java/haidnor/jvm/test/model/ThinDog.java | 13 + 269 files changed, 7632 insertions(+), 640 deletions(-) create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/DCMPG.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/DCMPL.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/FCMPG.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/FCMPL.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IFEQ.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IFGE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IFGT.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IFLE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IFLT.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IFNE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPEQ.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPNE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPEQ.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGT.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLT.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPNE.java create mode 100644 src/main/java/haidnor/jvm/instruction/comparisons/LCMP.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ACONST_NULL.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/BIPUSH.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/DCONST_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/DCONST_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/FCONST_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/FCONST_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_4.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_5.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/ICONST_M1.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/LCONST_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/LCONST_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/LDC.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/LDC2W.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/LDC_W.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/NOP.java create mode 100644 src/main/java/haidnor/jvm/instruction/constants/SIPUSH.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/ARETURN.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/DRETURN.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/FRETURN.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/IRETURN.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/LOOKUPSWITCH.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/LRETURN.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/RET.java create mode 100644 src/main/java/haidnor/jvm/instruction/control/RETURN.java rename src/main/java/haidnor/jvm/instruction/{ => control}/ReturnableInstruction.java (74%) create mode 100644 src/main/java/haidnor/jvm/instruction/control/TABLESWITCH.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/D2F.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/D2I.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/D2L.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/F2D.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/F2I.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/F2L.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/I2B.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/I2C.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/I2D.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/I2F.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/I2L.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/I2S.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/L2D.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/L2F.java create mode 100644 src/main/java/haidnor/jvm/instruction/conversions/L2I.java create mode 100644 src/main/java/haidnor/jvm/instruction/extended/GOTO.java create mode 100644 src/main/java/haidnor/jvm/instruction/extended/GOTO_W.java create mode 100644 src/main/java/haidnor/jvm/instruction/extended/IFNONNULL.java create mode 100644 src/main/java/haidnor/jvm/instruction/extended/IFNULL.java create mode 100644 src/main/java/haidnor/jvm/instruction/extended/MULTIANEWARRAY.java create mode 100644 src/main/java/haidnor/jvm/instruction/extended/WIDE.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/AALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ALOAD_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ALOAD_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ALOAD_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ALOAD_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/BALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/CALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/DALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/DLOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/DLOAD_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/DLOAD_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/DLOAD_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/DLOAD_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/FALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/FLOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/FLOAD_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/FLOAD_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/FLOAD_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/FLOAD_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/IALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ILOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ILOAD_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ILOAD_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ILOAD_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/ILOAD_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/LALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/LLOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/LLOAD_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/LLOAD_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/LLOAD_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/LLOAD_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/loads/SALOAD.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/DADD.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/DDIV.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/DMUL.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/DNEG.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/DREM.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/DSUB.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/FADD.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/FDIV.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/FMUL.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/FNEG.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/FREM.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/FSUB.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IADD.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IAND.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IDIV.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IINC.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IMUL.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/INEG.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IOR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IREM.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/ISHL.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/ISHR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/ISUB.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IUSHR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/IXOR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LADD.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LAND.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LDIV.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LMUL.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LNEG.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LOR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LREM.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LSHL.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LSHR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LSUB.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LUSHR.java create mode 100644 src/main/java/haidnor/jvm/instruction/math/LXOR.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/ARRAYLENGTH.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/ATHROW.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/CHECKCAST.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/GETFIELD.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/INVOKEDYNAMIC.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/INVOKESPECIAL.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/INVOKESTATIC.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/JSR.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/JSR_W.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/MONITORENTER.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/MONITOREXIT.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/NEW.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/NEWARRAY.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/PUTFIELD.java create mode 100644 src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/DUP.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/DUP2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/DUP_X1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/DUP_X2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/POP.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/POP2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stack/SWAP.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/AASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ASTORE_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ASTORE_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ASTORE_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ASTORE_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/BASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/CASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/DASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/DSTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/DSTORE_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/DSTORE_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/DSTORE_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/DSTORE_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/FASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/FSTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/FSTORE_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/FSTORE_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/FSTORE_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/FSTORE_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/IASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ISTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ISTORE_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ISTORE_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ISTORE_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/ISTORE_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/LASTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/LSTORE.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/LSTORE_0.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/LSTORE_1.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/LSTORE_2.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/LSTORE_3.java create mode 100644 src/main/java/haidnor/jvm/instruction/stores/SASTORE.java delete mode 100644 src/test/java/haidnor/jvm/Student.java delete mode 100644 src/test/java/haidnor/jvm/SuperStudent.java delete mode 100644 src/test/java/haidnor/jvm/test/BCELTest.java create mode 100644 src/test/java/haidnor/jvm/test/TestJVM.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/Func.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/HelloWorld.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/Human.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/Organism.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/Organism0.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/Student.java create mode 100644 src/test/java/haidnor/jvm/test/clazz/StudentEnum.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo2.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo3.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo4.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo5.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo6.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo7.java create mode 100644 src/test/java/haidnor/jvm/test/demo/Demo8.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_add.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_doWhile.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_enum_1.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_exception_1.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_exception_2.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_exception_3.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_exception_4.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_finally_1.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_finally_2.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_finally_3.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_for.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_foreach_1.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_foreach_2.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_foreach_3.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_helloWorld.java create mode 100644 src/test/java/haidnor/jvm/test/demo/demo_while.java create mode 100644 src/test/java/haidnor/jvm/test/demo1/Test1.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/Array.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/ClassA.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/DO_WHILE.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/GOTO.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/InnerClass.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/loads/Person.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/loads/Student.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/loads/Student1.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/DADD.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/FADD.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/IADD.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/IINC.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/ISUB.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/LADD.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/math/LSUB.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/references/CallStaticMethod.java create mode 100644 src/test/java/haidnor/jvm/test/instruction/references/NEW.java create mode 100644 src/test/java/haidnor/jvm/test/model/Animal.java create mode 100644 src/test/java/haidnor/jvm/test/model/CustomClassLoader.java create mode 100644 src/test/java/haidnor/jvm/test/model/Demo.java create mode 100644 src/test/java/haidnor/jvm/test/model/Dog.java create mode 100644 src/test/java/haidnor/jvm/test/model/DogTest.java create mode 100644 src/test/java/haidnor/jvm/test/model/ThinDog.java diff --git a/src/main/java/haidnor/jvm/HaidnorJVM.java b/src/main/java/haidnor/jvm/HaidnorJVM.java index dd7d419..14febdd 100644 --- a/src/main/java/haidnor/jvm/HaidnorJVM.java +++ b/src/main/java/haidnor/jvm/HaidnorJVM.java @@ -48,7 +48,7 @@ public class HaidnorJVM { JVMThreadHolder.set(new JVMThread()); JavaClass javaClass = classLoader.loadWithJar(jarFile, entry); Metaspace.registerJavaClass(javaClass); - JavaExecutionEngine.callMainMethod(javaClass); + JavaExecutionEngine.callMain(javaClass); return; } } @@ -62,7 +62,7 @@ public class HaidnorJVM { String path = cmd.getOptionValue("class"); JVMClassLoader bootClassLoader = new JVMClassLoader("ApplicationClassLoader"); JavaClass javaClass = bootClassLoader.loadWithAbsolutePath(path); - JavaExecutionEngine.callMainMethod(javaClass); + JavaExecutionEngine.callMain(javaClass); } } @@ -80,4 +80,11 @@ public class HaidnorJVM { return parser.parse(options, args); } + + public static void testRun(Class mainClass) { + JVMThreadHolder.set(new JVMThread()); + JVMClassLoader bootClassLoader = new JVMClassLoader("ApplicationClassLoader"); + JavaClass mainMeteKlass = bootClassLoader.loadWithClassPath(mainClass.getName().replace('.', '/')); + JavaExecutionEngine.callMain(mainMeteKlass); + } } \ No newline at end of file diff --git a/src/main/java/haidnor/jvm/bcel/classfile/Constant.java b/src/main/java/haidnor/jvm/bcel/classfile/Constant.java index 41baeab..9ca5491 100644 --- a/src/main/java/haidnor/jvm/bcel/classfile/Constant.java +++ b/src/main/java/haidnor/jvm/bcel/classfile/Constant.java @@ -29,6 +29,7 @@ import java.util.Objects; * classes keep closely to the JVM specification. */ public abstract class Constant implements Cloneable, Node { + public ConstantPool constantPool; private static BCELComparator bcelComparator = new BCELComparator() { @@ -160,6 +161,10 @@ public abstract class Constant implements Cloneable, Node { public abstract void dump(DataOutputStream file) throws IOException; + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + /** * Returns value as defined by given BCELComparator strategy. By default two Constant objects are said to be equal when * the result of toString() is equal. diff --git a/src/main/java/haidnor/jvm/bcel/classfile/ConstantMethodref.java b/src/main/java/haidnor/jvm/bcel/classfile/ConstantMethodref.java index 322848d..f69c7ed 100644 --- a/src/main/java/haidnor/jvm/bcel/classfile/ConstantMethodref.java +++ b/src/main/java/haidnor/jvm/bcel/classfile/ConstantMethodref.java @@ -17,6 +17,7 @@ package haidnor.jvm.bcel.classfile; import haidnor.jvm.bcel.Const; +import lombok.SneakyThrows; import java.io.DataInput; import java.io.IOException; @@ -63,4 +64,46 @@ public final class ConstantMethodref extends ConstantCP { public void accept(final Visitor v) { v.visitConstantMethodref(this); } + + public String getClassName() { + ConstantClass constClass = constantPool.getConstant(getClassIndex()); + return (String) constClass.getConstantValue(constantPool); + } + + public String getMethodName() { + ConstantNameAndType constNameAndType = constantPool.getConstant(getNameAndTypeIndex()); + return constNameAndType.getName(constantPool); + } + + public String getMethodSignature() { + ConstantNameAndType constNameAndType = constantPool.getConstant(getNameAndTypeIndex()); + return constNameAndType.getSignature(constantPool); + } + + public String getReturnType() { + return Utility.methodSignatureReturnType(getMethodSignature(), false); + } + + @SneakyThrows + public Class[] getParameterTypeArr() { + String[] argumentTypeArr = Utility.methodSignatureArgumentTypes(getMethodSignature(), false); + Class[] argumentClassArr = new Class[argumentTypeArr.length]; + for (int i = 0; i < argumentTypeArr.length; i++) { + Class argumentClass; + String argumentType = argumentTypeArr[i]; + argumentClass = switch (argumentType) { + case "byte" -> byte.class; + case "short" -> short.class; + case "boolean" -> boolean.class; + case "char" -> char.class; + case "int" -> int.class; + case "long" -> long.class; + case "float" -> float.class; + case "double" -> double.class; + default -> Class.forName(argumentType); + }; + argumentClassArr[i] = argumentClass; + } + return argumentClassArr; + } } diff --git a/src/main/java/haidnor/jvm/bcel/classfile/ConstantPool.java b/src/main/java/haidnor/jvm/bcel/classfile/ConstantPool.java index c453949..04851ce 100644 --- a/src/main/java/haidnor/jvm/bcel/classfile/ConstantPool.java +++ b/src/main/java/haidnor/jvm/bcel/classfile/ConstantPool.java @@ -318,6 +318,9 @@ public class ConstantPool implements Cloneable, Node, Iterable { throw new ClassFormatException("Constant pool at index " + index + " is null."); } } + if (c != null) { + c.setConstantPool(this); + } return c; } diff --git a/src/main/java/haidnor/jvm/bcel/classfile/JavaClass.java b/src/main/java/haidnor/jvm/bcel/classfile/JavaClass.java index 9c61ac4..d6f3ecd 100644 --- a/src/main/java/haidnor/jvm/bcel/classfile/JavaClass.java +++ b/src/main/java/haidnor/jvm/bcel/classfile/JavaClass.java @@ -24,8 +24,10 @@ import haidnor.jvm.bcel.util.ClassQueue; import haidnor.jvm.bcel.util.Repository; import haidnor.jvm.bcel.util.SyntheticRepository; import haidnor.jvm.classloader.JVMClassLoader; +import haidnor.jvm.rtda.Instance; import lombok.Getter; import lombok.Setter; +import lombok.SneakyThrows; import org.apache.commons.lang3.ArrayUtils; import java.io.*; @@ -896,5 +898,18 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl return null; } + @SneakyThrows + public Instance newInstance() { + // 创建对象存放字段的内存空间 + List javaFieldList = Arrays.asList(getFields()); + + // 创建 JVM 中的对象实例 + Instance obj = new Instance(javaFieldList, this); + // 加载父类 + if (this.getSuperClass() != null) { + obj.setSuperInstance(this.getSuperClass().newInstance()); + } + return obj; + } } diff --git a/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java b/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java index 2b855a2..a3de82e 100644 --- a/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java +++ b/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java @@ -5,7 +5,7 @@ import haidnor.jvm.bcel.Const; import haidnor.jvm.bcel.classfile.*; import haidnor.jvm.instruction.Instruction; import haidnor.jvm.instruction.InstructionFactory; -import haidnor.jvm.instruction.ReturnableInstruction; +import haidnor.jvm.instruction.control.ReturnableInstruction; import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.JVMThread; import haidnor.jvm.runtime.StackValue; @@ -26,8 +26,8 @@ public class JavaExecutionEngine { /** * 执行 public static void main(String[] args) 方法 */ - public static void callMainMethod(JavaClass javaClass) { - JavaMethod mainMethod = javaClass.getMainMethod(); + public static void callMain(JavaClass clazz) { + JavaMethod mainMethod = clazz.getMainMethod(); callMethod(null, mainMethod); } diff --git a/src/main/java/haidnor/jvm/instruction/InstructionFactory.java b/src/main/java/haidnor/jvm/instruction/InstructionFactory.java index 6d28943..e602194 100644 --- a/src/main/java/haidnor/jvm/instruction/InstructionFactory.java +++ b/src/main/java/haidnor/jvm/instruction/InstructionFactory.java @@ -1,5 +1,16 @@ package haidnor.jvm.instruction; +import haidnor.jvm.bcel.Const; +import haidnor.jvm.instruction.comparisons.*; +import haidnor.jvm.instruction.constants.*; +import haidnor.jvm.instruction.control.*; +import haidnor.jvm.instruction.conversions.*; +import haidnor.jvm.instruction.extended.*; +import haidnor.jvm.instruction.loads.*; +import haidnor.jvm.instruction.math.*; +import haidnor.jvm.instruction.references.*; +import haidnor.jvm.instruction.stack.*; +import haidnor.jvm.instruction.stores.*; import haidnor.jvm.util.CodeStream; public abstract class InstructionFactory { @@ -7,609 +18,609 @@ public abstract class InstructionFactory { public static Instruction creatInstruction(CodeStream codeStream) { int opcode = codeStream.readJavaVmOpcode(); switch (opcode) { -// case Const.NOP -> { -// return new NOP(codeStream); -// } -// case Const.ACONST_NULL -> { -// return new ACONST_NULL(codeStream); -// } -// case Const.ICONST_M1 -> { -// return new ICONST_M1(codeStream); -// } -// case Const.ICONST_0 -> { -// return new ICONST_0(codeStream); -// } -// case Const.ICONST_1 -> { -// return new ICONST_1(codeStream); -// } -// case Const.ICONST_2 -> { -// return new ICONST_2(codeStream); -// } -// case Const.ICONST_3 -> { -// return new ICONST_3(codeStream); -// } -// case Const.ICONST_4 -> { -// return new ICONST_4(codeStream); -// } -// case Const.ICONST_5 -> { -// return new ICONST_5(codeStream); -// } -// case Const.LCONST_0 -> { -// return new LCONST_0(codeStream); -// } -// case Const.LCONST_1 -> { -// return new LCONST_1(codeStream); -// } -// case Const.FCONST_1 -> { -// return new FCONST_1(codeStream); -// } -// case Const.FCONST_2 -> { -// return new FCONST_2(codeStream); -// } -// case Const.DCONST_0 -> { -// return new DCONST_0(codeStream); -// } -// case Const.DCONST_1 -> { -// return new DCONST_1(codeStream); -// } -// case Const.BIPUSH -> { -// return new BIPUSH(codeStream); -// } -// case Const.SIPUSH -> { -// return new SIPUSH(codeStream); -// } -// case Const.LDC -> { -// return new LDC(codeStream); -// } -// case Const.LDC_W -> { -// return new LDC_W(codeStream); -// } -// case Const.LDC2_W -> { -// return new LDC2W(codeStream); -// } -// case Const.ILOAD -> { -// return new ILOAD(codeStream); -// } -// case Const.LLOAD -> { -// return new LLOAD(codeStream); -// } -// case Const.FLOAD -> { -// return new FLOAD(codeStream); -// } -// case Const.DLOAD -> { -// return new DLOAD(codeStream); -// } -// case Const.ALOAD -> { -// return new ALOAD(codeStream); -// } -// case Const.ILOAD_0 -> { -// return new ILOAD_0(codeStream); -// } -// case Const.ILOAD_1 -> { -// return new ILOAD_1(codeStream); -// } -// case Const.ILOAD_2 -> { -// return new ILOAD_2(codeStream); -// } -// case Const.ILOAD_3 -> { -// return new ILOAD_3(codeStream); -// } -// case Const.LLOAD_0 -> { -// return new LLOAD_0(codeStream); -// } -// case Const.LLOAD_1 -> { -// return new LLOAD_1(codeStream); -// } -// case Const.LLOAD_2 -> { -// return new LLOAD_2(codeStream); -// } -// case Const.LLOAD_3 -> { -// return new LLOAD_3(codeStream); -// } -// case Const.FLOAD_0 -> { -// return new FLOAD_0(codeStream); -// } -// case Const.FLOAD_1 -> { -// return new FLOAD_1(codeStream); -// } -// case Const.FLOAD_2 -> { -// return new FLOAD_2(codeStream); -// } -// case Const.FLOAD_3 -> { -// return new FLOAD_3(codeStream); -// } -// case Const.DLOAD_0 -> { -// return new DLOAD_0(codeStream); -// } -// case Const.DLOAD_1 -> { -// return new DLOAD_1(codeStream); -// } -// case Const.DLOAD_2 -> { -// return new DLOAD_2(codeStream); -// } -// case Const.DLOAD_3 -> { -// return new DLOAD_3(codeStream); -// } -// case Const.ALOAD_0 -> { -// return new ALOAD_0(codeStream); -// } -// case Const.ALOAD_1 -> { -// return new ALOAD_1(codeStream); -// } -// case Const.ALOAD_2 -> { -// return new ALOAD_2(codeStream); -// } -// case Const.ALOAD_3 -> { -// return new ALOAD_3(codeStream); -// } -// case Const.IALOAD -> { -// return new IALOAD(codeStream); -// } -// case Const.LALOAD -> { -// return new LALOAD(codeStream); -// } -// case Const.FALOAD -> { -// return new FALOAD(codeStream); -// } -// case Const.DALOAD -> { -// return new DALOAD(codeStream); -// } -// case Const.AALOAD -> { -// return new AALOAD(codeStream); -// } -// case Const.BALOAD -> { -// return new BALOAD(codeStream); -// } -// case Const.CALOAD -> { -// return new CALOAD(codeStream); -// } -// case Const.SALOAD -> { -// return new SALOAD(codeStream); -// } -// case Const.ISTORE -> { -// return new ISTORE(codeStream); -// } -// case Const.LSTORE -> { -// return new LSTORE(codeStream); -// } -// case Const.FSTORE -> { -// return new FSTORE(codeStream); -// } -// case Const.DSTORE -> { -// return new DSTORE(codeStream); -// } -// case Const.ASTORE -> { -// return new ASTORE(codeStream); -// } -// case Const.ISTORE_0 -> { -// return new ISTORE_0(codeStream); -// } -// case Const.ISTORE_1 -> { -// return new ISTORE_1(codeStream); -// } -// case Const.ISTORE_2 -> { -// return new ISTORE_2(codeStream); -// } -// case Const.ISTORE_3 -> { -// return new ISTORE_3(codeStream); -// } -// case Const.LSTORE_0 -> { -// return new LSTORE_0(codeStream); -// } -// case Const.LSTORE_1 -> { -// return new LSTORE_1(codeStream); -// } -// case Const.LSTORE_2 -> { -// return new LSTORE_2(codeStream); -// } -// case Const.LSTORE_3 -> { -// return new LSTORE_3(codeStream); -// } -// case Const.FSTORE_0 -> { -// return new FSTORE_0(codeStream); -// } -// case Const.FSTORE_1 -> { -// return new FSTORE_1(codeStream); -// } -// case Const.FSTORE_2 -> { -// return new FSTORE_2(codeStream); -// } -// case Const.FSTORE_3 -> { -// return new FSTORE_3(codeStream); -// } -// case Const.DSTORE_0 -> { -// return new DSTORE_0(codeStream); -// } -// case Const.DSTORE_1 -> { -// return new DSTORE_1(codeStream); -// } -// case Const.DSTORE_2 -> { -// return new DSTORE_2(codeStream); -// } -// case Const.DSTORE_3 -> { -// return new DSTORE_3(codeStream); -// } -// case Const.ASTORE_0 -> { -// return new ASTORE_0(codeStream); -// } -// case Const.ASTORE_1 -> { -// return new ASTORE_1(codeStream); -// } -// case Const.ASTORE_2 -> { -// return new ASTORE_2(codeStream); -// } -// case Const.ASTORE_3 -> { -// return new ASTORE_3(codeStream); -// } -// case Const.IASTORE -> { -// return new IASTORE(codeStream); -// } -// case Const.LASTORE -> { -// return new LASTORE(codeStream); -// } -// case Const.FASTORE -> { -// return new FASTORE(codeStream); -// } -// case Const.DASTORE -> { -// return new DASTORE(codeStream); -// } -// case Const.AASTORE -> { -// return new AASTORE(codeStream); -// } -// case Const.BASTORE -> { -// return new BASTORE(codeStream); -// } -// case Const.CASTORE -> { -// return new CASTORE(codeStream); -// } -// case Const.SASTORE -> { -// return new SASTORE(codeStream); -// } -// case Const.POP -> { -// return new POP(codeStream); -// } -// case Const.POP2 -> { -// return new POP2(codeStream); -// } -// case Const.DUP -> { -// return new DUP(codeStream); -// } -// case Const.DUP_X1 -> { -// return new DUP_X1(codeStream); -// } -// case Const.DUP_X2 -> { -// return new DUP_X2(codeStream); -// } -// case Const.DUP2 -> { -// return new DUP2(codeStream); -// } -// case Const.DUP2_X1 -> { -// return new DUP2_X1(codeStream); -// } -// case Const.DUP2_X2 -> { -// return new DUP2_X2(codeStream); -// } -// case Const.SWAP -> { -// return new SWAP(codeStream); -// } -// case Const.IADD -> { -// return new IADD(codeStream); -// } -// case Const.LADD -> { -// return new LADD(codeStream); -// } -// case Const.FADD -> { -// return new FADD(codeStream); -// } -// case Const.DADD -> { -// return new DADD(codeStream); -// } -// case Const.ISUB -> { -// return new ISUB(codeStream); -// } -// case Const.LSUB -> { -// return new LSUB(codeStream); -// } -// case Const.FSUB -> { -// return new FSUB(codeStream); -// } -// case Const.DSUB -> { -// return new DSUB(codeStream); -// } -// case Const.IMUL -> { -// return new IMUL(codeStream); -// } -// case Const.LMUL -> { -// return new LMUL(codeStream); -// } -// case Const.FMUL -> { -// return new FMUL(codeStream); -// } -// case Const.DMUL -> { -// return new DMUL(codeStream); -// } -// case Const.IDIV -> { -// return new IDIV(codeStream); -// } -// case Const.LDIV -> { -// return new LDIV(codeStream); -// } -// case Const.FDIV -> { -// return new FDIV(codeStream); -// } -// case Const.DDIV -> { -// return new DDIV(codeStream); -// } -// case Const.IREM -> { -// return new IREM(codeStream); -// } -// case Const.LREM -> { -// return new LREM(codeStream); -// } -// case Const.FREM -> { -// return new FREM(codeStream); -// } -// case Const.DREM -> { -// return new DREM(codeStream); -// } -// case Const.INEG -> { -// return new INEG(codeStream); -// } -// case Const.LNEG -> { -// return new LNEG(codeStream); -// } -// case Const.FNEG -> { -// return new FNEG(codeStream); -// } -// case Const.DNEG -> { -// return new DNEG(codeStream); -// } -// case Const.ISHL -> { -// return new ISHL(codeStream); -// } -// case Const.LSHL -> { -// return new LSHL(codeStream); -// } -// case Const.ISHR -> { -// return new ISHR(codeStream); -// } -// case Const.LSHR -> { -// return new LSHR(codeStream); -// } -// case Const.IUSHR -> { -// return new IUSHR(codeStream); -// } -// case Const.LUSHR -> { -// return new LUSHR(codeStream); -// } -// case Const.IAND -> { -// return new IAND(codeStream); -// } -// case Const.LAND -> { -// return new LAND(codeStream); -// } -// case Const.IOR -> { -// return new IOR(codeStream); -// } -// case Const.LOR -> { -// return new LOR(codeStream); -// } -// case Const.IXOR -> { -// return new IXOR(codeStream); -// } -// case Const.LXOR -> { -// return new LXOR(codeStream); -// } -// case Const.IINC -> { -// return new IINC(codeStream); -// } -// case Const.I2L -> { -// return new I2L(codeStream); -// } -// case Const.I2F -> { -// return new I2F(codeStream); -// } -// case Const.I2D -> { -// return new I2D(codeStream); -// } -// case Const.L2I -> { -// return new L2I(codeStream); -// } -// case Const.L2F -> { -// return new L2F(codeStream); -// } -// case Const.L2D -> { -// return new L2D(codeStream); -// } -// case Const.F2I -> { -// return new F2I(codeStream); -// } -// case Const.F2L -> { -// return new F2L(codeStream); -// } -// case Const.F2D -> { -// return new F2D(codeStream); -// } -// case Const.D2I -> { -// return new D2I(codeStream); -// } -// case Const.D2L -> { -// return new D2L(codeStream); -// } -// case Const.D2F -> { -// return new D2F(codeStream); -// } -// case Const.I2B -> { -// return new I2B(codeStream); -// } -// case Const.I2C -> { -// return new I2C(codeStream); -// } -// case Const.I2S -> { -// return new I2S(codeStream); -// } -// case Const.LCMP -> { -// return new LCMP(codeStream); -// } -// case Const.FCMPL -> { -// return new FCMPL(codeStream); -// } -// case Const.FCMPG -> { -// return new FCMPG(codeStream); -// } -// case Const.DCMPL -> { -// return new DCMPL(codeStream); -// } -// case Const.DCMPG -> { -// return new DCMPG(codeStream); -// } -// case Const.IFEQ -> { -// return new IFEQ(codeStream); -// } -// case Const.IFNE -> { -// return new IFNE(codeStream); -// } -// case Const.IFLT -> { -// return new IFLT(codeStream); -// } -// case Const.IFGE -> { -// return new IFGE(codeStream); -// } -// case Const.IFGT -> { -// return new IFGT(codeStream); -// } -// case Const.IFLE -> { -// return new IFLE(codeStream); -// } -// case Const.IF_ICMPEQ -> { -// return new IF_ICMPEQ(codeStream); -// } -// case Const.IF_ICMPNE -> { -// return new IF_ICMPNE(codeStream); -// } -// case Const.IF_ICMPLT -> { -// return new IF_ICMPLT(codeStream); -// } -// case Const.IF_ICMPGE -> { -// return new IF_ICMPGE(codeStream); -// } -// case Const.IF_ICMPGT -> { -// return new IF_ICMPGT(codeStream); -// } -// case Const.IF_ICMPLE -> { -// return new IF_ICMPLE(codeStream); -// } -// case Const.IF_ACMPEQ -> { -// return new IF_ACMPEQ(codeStream); -// } -// case Const.IF_ACMPNE -> { -// return new IF_ACMPNE(codeStream); -// } -// case Const.GOTO -> { -// return new GOTO(codeStream); -// } -// case Const.JSR -> { -// return new JSR(codeStream); -// } -// case Const.RET -> { -// return new RET(codeStream); -// } -// case Const.TABLESWITCH -> { -// return new TABLESWITCH(codeStream); // TODO -// } -// case Const.LOOKUPSWITCH -> { -// return new LOOKUPSWITCH(codeStream); // TODO -// } -// case Const.IRETURN -> { -// return new IRETURN(codeStream); -// } -// case Const.LRETURN -> { -// return new LRETURN(codeStream); -// } -// case Const.FRETURN -> { -// return new FRETURN(codeStream); -// } -// case Const.DRETURN -> { -// return new DRETURN(codeStream); -// } -// case Const.ARETURN -> { -// return new ARETURN(codeStream); -// } -// case Const.RETURN -> { -// return new RETURN(codeStream); -// } -// case Const.GETSTATIC -> { -// return new GETSTATIC(codeStream); -// } -// case Const.PUTSTATIC -> { -// return new PUTSTATIC(codeStream); -// } -// case Const.GETFIELD -> { -// return new GETFIELD(codeStream); -// } -// case Const.PUTFIELD -> { -// return new PUTFIELD(codeStream); -// } -// case Const.INVOKEVIRTUAL -> { -// return new INVOKEVIRTUAL(codeStream); -// } -// case Const.INVOKESPECIAL -> { -// return new INVOKESPECIAL(codeStream); -// } -// case Const.INVOKESTATIC -> { -// return new INVOKESTATIC(codeStream); -// } -// case Const.INVOKEINTERFACE -> { -// return new INVOKEINTERFACE(codeStream); -// } -// case Const.INVOKEDYNAMIC -> { -// return new INVOKEDYNAMIC(codeStream); // TODO -// } -// case Const.NEW -> { -// return new NEW(codeStream); -// } -// case Const.NEWARRAY -> { -// return new NEWARRAY(codeStream); -// } -// case Const.ANEWARRAY -> { -// return new ANEWARRAY(codeStream); -// } -// case Const.ARRAYLENGTH -> { -// return new ARRAYLENGTH(codeStream); -// } -// case Const.ATHROW -> { -// return new ATHROW(codeStream); -// } -// case Const.CHECKCAST -> { -// return new CHECKCAST(codeStream); -// } -// case Const.INSTANCEOF -> { -// return new INSTANCEOF(codeStream); -// } -// case Const.MONITORENTER -> { -// return new MONITORENTER(codeStream); -// } -// case Const.MONITOREXIT -> { -// return new MONITOREXIT(codeStream); -// } -// case Const.WIDE -> { -// return new WIDE(codeStream); -// } -// case Const.MULTIANEWARRAY -> { -// return new MULTIANEWARRAY(codeStream); -// } -// case Const.IFNULL -> { -// return new IFNULL(codeStream); -// } -// case Const.IFNONNULL -> { -// return new IFNONNULL(codeStream); -// } -// case Const.GOTO_W -> { -// return new GOTO_W(codeStream); -// } -// case Const.JSR_W -> { -// return new JSR_W(codeStream); -// } + case Const.NOP -> { + return new NOP(codeStream); + } + case Const.ACONST_NULL -> { + return new ACONST_NULL(codeStream); + } + case Const.ICONST_M1 -> { + return new ICONST_M1(codeStream); + } + case Const.ICONST_0 -> { + return new ICONST_0(codeStream); + } + case Const.ICONST_1 -> { + return new ICONST_1(codeStream); + } + case Const.ICONST_2 -> { + return new ICONST_2(codeStream); + } + case Const.ICONST_3 -> { + return new ICONST_3(codeStream); + } + case Const.ICONST_4 -> { + return new ICONST_4(codeStream); + } + case Const.ICONST_5 -> { + return new ICONST_5(codeStream); + } + case Const.LCONST_0 -> { + return new LCONST_0(codeStream); + } + case Const.LCONST_1 -> { + return new LCONST_1(codeStream); + } + case Const.FCONST_1 -> { + return new FCONST_1(codeStream); + } + case Const.FCONST_2 -> { + return new FCONST_2(codeStream); + } + case Const.DCONST_0 -> { + return new DCONST_0(codeStream); + } + case Const.DCONST_1 -> { + return new DCONST_1(codeStream); + } + case Const.BIPUSH -> { + return new BIPUSH(codeStream); + } + case Const.SIPUSH -> { + return new SIPUSH(codeStream); + } + case Const.LDC -> { + return new LDC(codeStream); + } + case Const.LDC_W -> { + return new LDC_W(codeStream); + } + case Const.LDC2_W -> { + return new LDC2W(codeStream); + } + case Const.ILOAD -> { + return new ILOAD(codeStream); + } + case Const.LLOAD -> { + return new LLOAD(codeStream); + } + case Const.FLOAD -> { + return new FLOAD(codeStream); + } + case Const.DLOAD -> { + return new DLOAD(codeStream); + } + case Const.ALOAD -> { + return new ALOAD(codeStream); + } + case Const.ILOAD_0 -> { + return new ILOAD_0(codeStream); + } + case Const.ILOAD_1 -> { + return new ILOAD_1(codeStream); + } + case Const.ILOAD_2 -> { + return new ILOAD_2(codeStream); + } + case Const.ILOAD_3 -> { + return new ILOAD_3(codeStream); + } + case Const.LLOAD_0 -> { + return new LLOAD_0(codeStream); + } + case Const.LLOAD_1 -> { + return new LLOAD_1(codeStream); + } + case Const.LLOAD_2 -> { + return new LLOAD_2(codeStream); + } + case Const.LLOAD_3 -> { + return new LLOAD_3(codeStream); + } + case Const.FLOAD_0 -> { + return new FLOAD_0(codeStream); + } + case Const.FLOAD_1 -> { + return new FLOAD_1(codeStream); + } + case Const.FLOAD_2 -> { + return new FLOAD_2(codeStream); + } + case Const.FLOAD_3 -> { + return new FLOAD_3(codeStream); + } + case Const.DLOAD_0 -> { + return new DLOAD_0(codeStream); + } + case Const.DLOAD_1 -> { + return new DLOAD_1(codeStream); + } + case Const.DLOAD_2 -> { + return new DLOAD_2(codeStream); + } + case Const.DLOAD_3 -> { + return new DLOAD_3(codeStream); + } + case Const.ALOAD_0 -> { + return new ALOAD_0(codeStream); + } + case Const.ALOAD_1 -> { + return new ALOAD_1(codeStream); + } + case Const.ALOAD_2 -> { + return new ALOAD_2(codeStream); + } + case Const.ALOAD_3 -> { + return new ALOAD_3(codeStream); + } + case Const.IALOAD -> { + return new IALOAD(codeStream); + } + case Const.LALOAD -> { + return new LALOAD(codeStream); + } + case Const.FALOAD -> { + return new FALOAD(codeStream); + } + case Const.DALOAD -> { + return new DALOAD(codeStream); + } + case Const.AALOAD -> { + return new AALOAD(codeStream); + } + case Const.BALOAD -> { + return new BALOAD(codeStream); + } + case Const.CALOAD -> { + return new CALOAD(codeStream); + } + case Const.SALOAD -> { + return new SALOAD(codeStream); + } + case Const.ISTORE -> { + return new ISTORE(codeStream); + } + case Const.LSTORE -> { + return new LSTORE(codeStream); + } + case Const.FSTORE -> { + return new FSTORE(codeStream); + } + case Const.DSTORE -> { + return new DSTORE(codeStream); + } + case Const.ASTORE -> { + return new ASTORE(codeStream); + } + case Const.ISTORE_0 -> { + return new ISTORE_0(codeStream); + } + case Const.ISTORE_1 -> { + return new ISTORE_1(codeStream); + } + case Const.ISTORE_2 -> { + return new ISTORE_2(codeStream); + } + case Const.ISTORE_3 -> { + return new ISTORE_3(codeStream); + } + case Const.LSTORE_0 -> { + return new LSTORE_0(codeStream); + } + case Const.LSTORE_1 -> { + return new LSTORE_1(codeStream); + } + case Const.LSTORE_2 -> { + return new LSTORE_2(codeStream); + } + case Const.LSTORE_3 -> { + return new LSTORE_3(codeStream); + } + case Const.FSTORE_0 -> { + return new FSTORE_0(codeStream); + } + case Const.FSTORE_1 -> { + return new FSTORE_1(codeStream); + } + case Const.FSTORE_2 -> { + return new FSTORE_2(codeStream); + } + case Const.FSTORE_3 -> { + return new FSTORE_3(codeStream); + } + case Const.DSTORE_0 -> { + return new DSTORE_0(codeStream); + } + case Const.DSTORE_1 -> { + return new DSTORE_1(codeStream); + } + case Const.DSTORE_2 -> { + return new DSTORE_2(codeStream); + } + case Const.DSTORE_3 -> { + return new DSTORE_3(codeStream); + } + case Const.ASTORE_0 -> { + return new ASTORE_0(codeStream); + } + case Const.ASTORE_1 -> { + return new ASTORE_1(codeStream); + } + case Const.ASTORE_2 -> { + return new ASTORE_2(codeStream); + } + case Const.ASTORE_3 -> { + return new ASTORE_3(codeStream); + } + case Const.IASTORE -> { + return new IASTORE(codeStream); + } + case Const.LASTORE -> { + return new LASTORE(codeStream); + } + case Const.FASTORE -> { + return new FASTORE(codeStream); + } + case Const.DASTORE -> { + return new DASTORE(codeStream); + } + case Const.AASTORE -> { + return new AASTORE(codeStream); + } + case Const.BASTORE -> { + return new BASTORE(codeStream); + } + case Const.CASTORE -> { + return new CASTORE(codeStream); + } + case Const.SASTORE -> { + return new SASTORE(codeStream); + } + case Const.POP -> { + return new POP(codeStream); + } + case Const.POP2 -> { + return new POP2(codeStream); + } + case Const.DUP -> { + return new DUP(codeStream); + } + case Const.DUP_X1 -> { + return new DUP_X1(codeStream); + } + case Const.DUP_X2 -> { + return new DUP_X2(codeStream); + } + case Const.DUP2 -> { + return new DUP2(codeStream); + } + case Const.DUP2_X1 -> { + return new DUP2_X1(codeStream); + } + case Const.DUP2_X2 -> { + return new DUP2_X2(codeStream); + } + case Const.SWAP -> { + return new SWAP(codeStream); + } + case Const.IADD -> { + return new IADD(codeStream); + } + case Const.LADD -> { + return new LADD(codeStream); + } + case Const.FADD -> { + return new FADD(codeStream); + } + case Const.DADD -> { + return new DADD(codeStream); + } + case Const.ISUB -> { + return new ISUB(codeStream); + } + case Const.LSUB -> { + return new LSUB(codeStream); + } + case Const.FSUB -> { + return new FSUB(codeStream); + } + case Const.DSUB -> { + return new DSUB(codeStream); + } + case Const.IMUL -> { + return new IMUL(codeStream); + } + case Const.LMUL -> { + return new LMUL(codeStream); + } + case Const.FMUL -> { + return new FMUL(codeStream); + } + case Const.DMUL -> { + return new DMUL(codeStream); + } + case Const.IDIV -> { + return new IDIV(codeStream); + } + case Const.LDIV -> { + return new LDIV(codeStream); + } + case Const.FDIV -> { + return new FDIV(codeStream); + } + case Const.DDIV -> { + return new DDIV(codeStream); + } + case Const.IREM -> { + return new IREM(codeStream); + } + case Const.LREM -> { + return new LREM(codeStream); + } + case Const.FREM -> { + return new FREM(codeStream); + } + case Const.DREM -> { + return new DREM(codeStream); + } + case Const.INEG -> { + return new INEG(codeStream); + } + case Const.LNEG -> { + return new LNEG(codeStream); + } + case Const.FNEG -> { + return new FNEG(codeStream); + } + case Const.DNEG -> { + return new DNEG(codeStream); + } + case Const.ISHL -> { + return new ISHL(codeStream); + } + case Const.LSHL -> { + return new LSHL(codeStream); + } + case Const.ISHR -> { + return new ISHR(codeStream); + } + case Const.LSHR -> { + return new LSHR(codeStream); + } + case Const.IUSHR -> { + return new IUSHR(codeStream); + } + case Const.LUSHR -> { + return new LUSHR(codeStream); + } + case Const.IAND -> { + return new IAND(codeStream); + } + case Const.LAND -> { + return new LAND(codeStream); + } + case Const.IOR -> { + return new IOR(codeStream); + } + case Const.LOR -> { + return new LOR(codeStream); + } + case Const.IXOR -> { + return new IXOR(codeStream); + } + case Const.LXOR -> { + return new LXOR(codeStream); + } + case Const.IINC -> { + return new IINC(codeStream); + } + case Const.I2L -> { + return new I2L(codeStream); + } + case Const.I2F -> { + return new I2F(codeStream); + } + case Const.I2D -> { + return new I2D(codeStream); + } + case Const.L2I -> { + return new L2I(codeStream); + } + case Const.L2F -> { + return new L2F(codeStream); + } + case Const.L2D -> { + return new L2D(codeStream); + } + case Const.F2I -> { + return new F2I(codeStream); + } + case Const.F2L -> { + return new F2L(codeStream); + } + case Const.F2D -> { + return new F2D(codeStream); + } + case Const.D2I -> { + return new D2I(codeStream); + } + case Const.D2L -> { + return new D2L(codeStream); + } + case Const.D2F -> { + return new D2F(codeStream); + } + case Const.I2B -> { + return new I2B(codeStream); + } + case Const.I2C -> { + return new I2C(codeStream); + } + case Const.I2S -> { + return new I2S(codeStream); + } + case Const.LCMP -> { + return new LCMP(codeStream); + } + case Const.FCMPL -> { + return new FCMPL(codeStream); + } + case Const.FCMPG -> { + return new FCMPG(codeStream); + } + case Const.DCMPL -> { + return new DCMPL(codeStream); + } + case Const.DCMPG -> { + return new DCMPG(codeStream); + } + case Const.IFEQ -> { + return new IFEQ(codeStream); + } + case Const.IFNE -> { + return new IFNE(codeStream); + } + case Const.IFLT -> { + return new IFLT(codeStream); + } + case Const.IFGE -> { + return new IFGE(codeStream); + } + case Const.IFGT -> { + return new IFGT(codeStream); + } + case Const.IFLE -> { + return new IFLE(codeStream); + } + case Const.IF_ICMPEQ -> { + return new IF_ICMPEQ(codeStream); + } + case Const.IF_ICMPNE -> { + return new IF_ICMPNE(codeStream); + } + case Const.IF_ICMPLT -> { + return new IF_ICMPLT(codeStream); + } + case Const.IF_ICMPGE -> { + return new IF_ICMPGE(codeStream); + } + case Const.IF_ICMPGT -> { + return new IF_ICMPGT(codeStream); + } + case Const.IF_ICMPLE -> { + return new IF_ICMPLE(codeStream); + } + case Const.IF_ACMPEQ -> { + return new IF_ACMPEQ(codeStream); + } + case Const.IF_ACMPNE -> { + return new IF_ACMPNE(codeStream); + } + case Const.GOTO -> { + return new GOTO(codeStream); + } + case Const.JSR -> { + return new JSR(codeStream); + } + case Const.RET -> { + return new RET(codeStream); + } + case Const.TABLESWITCH -> { + return new TABLESWITCH(codeStream); // TODO + } + case Const.LOOKUPSWITCH -> { + return new LOOKUPSWITCH(codeStream); // TODO + } + case Const.IRETURN -> { + return new IRETURN(codeStream); + } + case Const.LRETURN -> { + return new LRETURN(codeStream); + } + case Const.FRETURN -> { + return new FRETURN(codeStream); + } + case Const.DRETURN -> { + return new DRETURN(codeStream); + } + case Const.ARETURN -> { + return new ARETURN(codeStream); + } + case Const.RETURN -> { + return new RETURN(codeStream); + } + case Const.GETSTATIC -> { + return new GETSTATIC(codeStream); + } + case Const.PUTSTATIC -> { + return new PUTSTATIC(codeStream); + } + case Const.GETFIELD -> { + return new GETFIELD(codeStream); + } + case Const.PUTFIELD -> { + return new PUTFIELD(codeStream); + } + case Const.INVOKEVIRTUAL -> { + return new INVOKEVIRTUAL(codeStream); + } + case Const.INVOKESPECIAL -> { + return new INVOKESPECIAL(codeStream); + } + case Const.INVOKESTATIC -> { + return new INVOKESTATIC(codeStream); + } + case Const.INVOKEINTERFACE -> { + return new INVOKEINTERFACE(codeStream); + } + case Const.INVOKEDYNAMIC -> { + return new INVOKEDYNAMIC(codeStream); // TODO + } + case Const.NEW -> { + return new NEW(codeStream); + } + case Const.NEWARRAY -> { + return new NEWARRAY(codeStream); + } + case Const.ANEWARRAY -> { + return new ANEWARRAY(codeStream); + } + case Const.ARRAYLENGTH -> { + return new ARRAYLENGTH(codeStream); + } + case Const.ATHROW -> { + return new ATHROW(codeStream); + } + case Const.CHECKCAST -> { + return new CHECKCAST(codeStream); + } + case Const.INSTANCEOF -> { + return new INSTANCEOF(codeStream); + } + case Const.MONITORENTER -> { + return new MONITORENTER(codeStream); + } + case Const.MONITOREXIT -> { + return new MONITOREXIT(codeStream); + } + case Const.WIDE -> { + return new WIDE(codeStream); + } + case Const.MULTIANEWARRAY -> { + return new MULTIANEWARRAY(codeStream); + } + case Const.IFNULL -> { + return new IFNULL(codeStream); + } + case Const.IFNONNULL -> { + return new IFNONNULL(codeStream); + } + case Const.GOTO_W -> { + return new GOTO_W(codeStream); + } + case Const.JSR_W -> { + return new JSR_W(codeStream); + } default -> throw new Error("Unknown JavaVM opcode " + opcode); } } diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/DCMPG.java b/src/main/java/haidnor/jvm/instruction/comparisons/DCMPG.java new file mode 100644 index 0000000..3fe4f61 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/DCMPG.java @@ -0,0 +1,31 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * @author wang xiang + */ +public class DCMPG extends Instruction { + + public DCMPG(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double v2 = frame.popDouble(); + double v1 = frame.popDouble(); + if (v1 == v2) { + frame.pushInt(0); + return; + } + if (v1 < v2) { + frame.pushInt(-1); + return; + } + frame.pushInt(1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/DCMPL.java b/src/main/java/haidnor/jvm/instruction/comparisons/DCMPL.java new file mode 100644 index 0000000..0f2b8f3 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/DCMPL.java @@ -0,0 +1,31 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * @author wang xiang + */ +public class DCMPL extends Instruction { + + public DCMPL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Double v2 = frame.popDouble(); + Double v1 = frame.popDouble(); + if (v1.equals(v2)) { + frame.pushInt(0); + return; + } + if (v1 < v2) { + frame.pushInt(-1); + return; + } + frame.pushInt(1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/FCMPG.java b/src/main/java/haidnor/jvm/instruction/comparisons/FCMPG.java new file mode 100644 index 0000000..d57fd7e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/FCMPG.java @@ -0,0 +1,30 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +/** + * @author wang xiang + */ +public class FCMPG extends Instruction { + + public FCMPG(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float v2 = frame.popFloat(); + float v1 = frame.popFloat(); + if (v1 == v2) { + frame.pushInt(0); + return; + } + if (v1 < v2) { + frame.pushInt(-1); + return; + } + frame.pushInt(1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/FCMPL.java b/src/main/java/haidnor/jvm/instruction/comparisons/FCMPL.java new file mode 100644 index 0000000..5dba400 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/FCMPL.java @@ -0,0 +1,30 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +/** + * @author wang xiang + */ +public class FCMPL extends Instruction { + + public FCMPL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float v2 = frame.popFloat(); + float v1 = frame.popFloat(); + if (v1 == v2) { + frame.pushInt(0); + return; + } + if (v1 < v2) { + frame.pushInt(-1); + return; + } + frame.pushInt(1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IFEQ.java b/src/main/java/haidnor/jvm/instruction/comparisons/IFEQ.java new file mode 100644 index 0000000..a9fb754 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IFEQ.java @@ -0,0 +1,40 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFEQ extends Instruction { + + private final int offSet; + + public IFEQ(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if (v1.getValue() instanceof Boolean) { + if (!((boolean) v1.getValue())) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } else { + if ((int) v1.getValue() == 0) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IFGE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IFGE.java new file mode 100644 index 0000000..8a4e263 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IFGE.java @@ -0,0 +1,34 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFGE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFGE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if ((int) v1.getValue() >= 0) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IFGT.java b/src/main/java/haidnor/jvm/instruction/comparisons/IFGT.java new file mode 100644 index 0000000..d91b3aa --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IFGT.java @@ -0,0 +1,34 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFGT extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFGT(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if ((int) v1.getValue() > 0) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IFLE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IFLE.java new file mode 100644 index 0000000..566deb7 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IFLE.java @@ -0,0 +1,34 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFLE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFLE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if ((int) v1.getValue() <= 0) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IFLT.java b/src/main/java/haidnor/jvm/instruction/comparisons/IFLT.java new file mode 100644 index 0000000..aba66af --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IFLT.java @@ -0,0 +1,34 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFLT extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFLT(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if ((int) v1.getValue() < 0) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IFNE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IFNE.java new file mode 100644 index 0000000..76c7fba --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IFNE.java @@ -0,0 +1,43 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFNE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFNE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if (v1.getValue() instanceof Boolean) { + if (((boolean) v1.getValue())) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } else { + if ((int) v1.getValue() != 0) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPEQ.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPEQ.java new file mode 100644 index 0000000..47f74ac --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPEQ.java @@ -0,0 +1,36 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +/** + * @author wang xiang + */ +public class IF_ACMPEQ extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ACMPEQ(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + Object val2 = frame.popRef(); + Object val1 = frame.popRef(); + if (val1 == val2) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPNE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPNE.java new file mode 100644 index 0000000..fcadaf6 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ACMPNE.java @@ -0,0 +1,36 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +/** + * @author wang xiang + */ +public class IF_ACMPNE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ACMPNE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + Object val2 = frame.popRef(); + Object val1 = frame.popRef(); + if (val1 != val2) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPEQ.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPEQ.java new file mode 100644 index 0000000..7a73bdb --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPEQ.java @@ -0,0 +1,42 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @author wang xiang + * @see Opcode + * definitions in The Java Virtual Machine Specification + */ +public class IF_ICMPEQ extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ICMPEQ(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + StackValue v2 = frame.pop(); + + if ((int) v1.getValue() == (int) v2.getValue()) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGE.java new file mode 100644 index 0000000..92da062 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGE.java @@ -0,0 +1,42 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode + * definitions in The Java Virtual Machine Specification + */ +public class IF_ICMPGE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ICMPGE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v2 = frame.pop(); + StackValue v1 = frame.pop(); + + if ((int) v1.getValue() >= (int) v2.getValue()) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGT.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGT.java new file mode 100644 index 0000000..c4dc330 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPGT.java @@ -0,0 +1,42 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode + * definitions in The Java Virtual Machine Specification + */ +public class IF_ICMPGT extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ICMPGT(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v2 = frame.pop(); + StackValue v1 = frame.pop(); + + if ((int) v1.getValue() > (int) v2.getValue()) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLE.java new file mode 100644 index 0000000..73d7768 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLE.java @@ -0,0 +1,37 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode + * definitions in The Java Virtual Machine Specification + */ +public class IF_ICMPLE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ICMPLE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v2 = frame.pop(); + StackValue v1 = frame.pop(); + + if ((int) v1.getValue() <= (int) v2.getValue()) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLT.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLT.java new file mode 100644 index 0000000..4d5ae29 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPLT.java @@ -0,0 +1,42 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode + * definitions in The Java Virtual Machine Specification + */ +public class IF_ICMPLT extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ICMPLT(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v2 = frame.pop(); + StackValue v1 = frame.pop(); + + if ((int) v1.getValue() < (int) v2.getValue()) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPNE.java b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPNE.java new file mode 100644 index 0000000..acca433 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/IF_ICMPNE.java @@ -0,0 +1,42 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode + * definitions in The Java Virtual Machine Specification + */ +public class IF_ICMPNE extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IF_ICMPNE(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + StackValue v2 = frame.pop(); + + if ((int) v1.getValue() != (int) v2.getValue()) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/comparisons/LCMP.java b/src/main/java/haidnor/jvm/instruction/comparisons/LCMP.java new file mode 100644 index 0000000..60e3daf --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/comparisons/LCMP.java @@ -0,0 +1,28 @@ +package haidnor.jvm.instruction.comparisons; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LCMP extends Instruction { + + public LCMP(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Long v2 = frame.popLong(); + Long v1 = frame.popLong(); + if (v1.equals(v2)) { + frame.pushInt(0); + return; + } + if (v1 < v2) { + frame.pushInt(-1); + return; + } + frame.pushInt(1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ACONST_NULL.java b/src/main/java/haidnor/jvm/instruction/constants/ACONST_NULL.java new file mode 100644 index 0000000..2af3132 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ACONST_NULL.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ACONST_NULL extends Instruction { + + public ACONST_NULL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_OBJECT, null)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/BIPUSH.java b/src/main/java/haidnor/jvm/instruction/constants/BIPUSH.java new file mode 100644 index 0000000..115670f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/BIPUSH.java @@ -0,0 +1,29 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions in + * The Java Virtual Machine Specification + */ +public class BIPUSH extends Instruction { + + private final int value; + + public BIPUSH(CodeStream codeStream) { + super(codeStream); + this.value = codeStream.readByte(this); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/DCONST_0.java b/src/main/java/haidnor/jvm/instruction/constants/DCONST_0.java new file mode 100644 index 0000000..d177a7c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/DCONST_0.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions + * in The Java Virtual Machine Specification + */ +public class DCONST_0 extends Instruction { + + public DCONST_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_DOUBLE, 0.0D)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/DCONST_1.java b/src/main/java/haidnor/jvm/instruction/constants/DCONST_1.java new file mode 100644 index 0000000..336afd9 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/DCONST_1.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions + * in The Java Virtual Machine Specification + */ +public class DCONST_1 extends Instruction { + + public DCONST_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_DOUBLE, 1.0D)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/FCONST_1.java b/src/main/java/haidnor/jvm/instruction/constants/FCONST_1.java new file mode 100644 index 0000000..9d6d767 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/FCONST_1.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions + * in The Java Virtual Machine Specification + */ +public class FCONST_1 extends Instruction { + + public FCONST_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_FLOAT, 1.0f)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/FCONST_2.java b/src/main/java/haidnor/jvm/instruction/constants/FCONST_2.java new file mode 100644 index 0000000..06da1af --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/FCONST_2.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions + * in The Java Virtual Machine Specification + */ +public class FCONST_2 extends Instruction { + + public FCONST_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_FLOAT, 2.0f)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_0.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_0.java new file mode 100644 index 0000000..9c8f7ff --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_0.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_0 extends Instruction { + + public ICONST_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, 0)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_1.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_1.java new file mode 100644 index 0000000..b500e45 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_1.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_1 extends Instruction { + + public ICONST_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, 1)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_2.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_2.java new file mode 100644 index 0000000..f7479f9 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_2.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_2 extends Instruction { + + public ICONST_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, 2)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_3.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_3.java new file mode 100644 index 0000000..986df4a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_3.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_3 extends Instruction { + + public ICONST_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, 3)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_4.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_4.java new file mode 100644 index 0000000..0170f5f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_4.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_4 extends Instruction { + + public ICONST_4(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, 4)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_5.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_5.java new file mode 100644 index 0000000..7ee2d8a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_5.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_5 extends Instruction { + + public ICONST_5(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, 5)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/ICONST_M1.java b/src/main/java/haidnor/jvm/instruction/constants/ICONST_M1.java new file mode 100644 index 0000000..5cf6fd8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/ICONST_M1.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iconst_i + */ +public class ICONST_M1 extends Instruction { + + public ICONST_M1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, -1)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/LCONST_0.java b/src/main/java/haidnor/jvm/instruction/constants/LCONST_0.java new file mode 100644 index 0000000..65feb10 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/LCONST_0.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions + * in The Java Virtual Machine Specification + */ +public class LCONST_0 extends Instruction { + + public LCONST_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_LONG, 0L)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/LCONST_1.java b/src/main/java/haidnor/jvm/instruction/constants/LCONST_1.java new file mode 100644 index 0000000..5889ceb --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/LCONST_1.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions + * in The Java Virtual Machine Specification + */ +public class LCONST_1 extends Instruction { + + public LCONST_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_LONG, 1L)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/LDC.java b/src/main/java/haidnor/jvm/instruction/constants/LDC.java new file mode 100644 index 0000000..eeb2178 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/LDC.java @@ -0,0 +1,58 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * Java VM opcode. + * + * @see Opcode definitions in The + * Java Virtual Machine Specification + */ +public class LDC extends Instruction { + + private final int constantIndex; + + public LDC(CodeStream codeStream) { + super(codeStream); + this.constantIndex = codeStream.readUnsignedByte(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + + // 从常量池中获取值 + Constant constant = constantPool.getConstant(constantIndex); + + switch (constant.getTag()) { + case Const.CONSTANT_Integer: { + ConstantInteger constantInteger = (ConstantInteger) constant; + Object value = constantInteger.getConstantValue(constantPool); + frame.push(new StackValue(Const.T_INT, value)); + break; + } + case Const.CONSTANT_Float: { + ConstantFloat constantFloat = (ConstantFloat) constant; + Object value = constantFloat.getConstantValue(constantPool); + frame.push(new StackValue(Const.T_FLOAT, value)); + break; + } + case Const.CONSTANT_String: { + ConstantString constString = (ConstantString) constant; + Object value = constString.getConstantValue(constantPool); + frame.push(new StackValue(Const.T_OBJECT, value)); + break; + } + default: + throw new Error("not supported LDC type" + constant.getTag()); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/LDC2W.java b/src/main/java/haidnor/jvm/instruction/constants/LDC2W.java new file mode 100644 index 0000000..7795f36 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/LDC2W.java @@ -0,0 +1,48 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.Constant; +import haidnor.jvm.bcel.classfile.ConstantDouble; +import haidnor.jvm.bcel.classfile.ConstantLong; +import haidnor.jvm.bcel.classfile.ConstantPool; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +/** + * 将 long 或 double 型常量从常量池中推送至栈顶 (宽索引) + */ +public class LDC2W extends Instruction { + + private final byte constantTag; + + private long longValue; + + private double doubleValue; + + public LDC2W(CodeStream codeStream) { + super(codeStream); + int index = codeStream.readUnsignedShort(this); + ConstantPool constantPool = codeStream.getCode().getConstantPool(); + Constant constant = constantPool.getConstant(index); + this.constantTag = constant.getTag(); + if (constantTag == Const.CONSTANT_Long) { + ConstantLong constantLong = (ConstantLong) constant; + this.longValue = constantLong.getBytes(); + } else if (constantTag == Const.CONSTANT_Double) { + ConstantDouble constantDouble = (ConstantDouble) constant; + this.doubleValue = constantDouble.getBytes(); + } + } + + @Override + public void execute(Frame frame) { + if (constantTag == Const.CONSTANT_Long) { + frame.push(new StackValue(Const.T_LONG, this.longValue)); + } else if (constantTag == Const.CONSTANT_Double) { + frame.push(new StackValue(Const.T_DOUBLE, this.doubleValue)); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/LDC_W.java b/src/main/java/haidnor/jvm/instruction/constants/LDC_W.java new file mode 100644 index 0000000..db891ec --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/LDC_W.java @@ -0,0 +1,58 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * Java VM opcode. + * + * @see Opcode definitions in + * The Java Virtual Machine Specification + */ +public class LDC_W extends Instruction { + + private final int constantIndex; + + public LDC_W(CodeStream codeStream) { + super(codeStream); + this.constantIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + + // 从常量池中获取值 + Constant constant = constantPool.getConstant(constantIndex); + + switch (constant.getTag()) { + case Const.CONSTANT_Integer: { + ConstantInteger constantInteger = (ConstantInteger) constant; + Object value = constantInteger.getConstantValue(constantPool); + frame.push(new StackValue(Const.T_INT, value)); + break; + } + case Const.CONSTANT_Float: { + ConstantFloat constantFloat = (ConstantFloat) constant; + Object value = constantFloat.getConstantValue(constantPool); + frame.push(new StackValue(Const.T_FLOAT, value)); + break; + } + case Const.CONSTANT_String: { + ConstantString constString = (ConstantString) constant; + Object value = constString.getConstantValue(constantPool); + frame.push(new StackValue(Const.T_OBJECT, value)); + break; + } + default: + throw new Error("not supported LDCW type" + constant.getTag()); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/NOP.java b/src/main/java/haidnor/jvm/instruction/constants/NOP.java new file mode 100644 index 0000000..2ffdbea --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/NOP.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode definitions in The + * Java Virtual Machine Specification + */ +public class NOP extends Instruction { + + public NOP(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/constants/SIPUSH.java b/src/main/java/haidnor/jvm/instruction/constants/SIPUSH.java new file mode 100644 index 0000000..b1c4d3a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/constants/SIPUSH.java @@ -0,0 +1,29 @@ +package haidnor.jvm.instruction.constants; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * Java VM opcode. + * + * @see Opcode definitions in + * The Java Virtual Machine Specification + */ +public class SIPUSH extends Instruction { + + private final int value; + + public SIPUSH(CodeStream codeStream) { + super(codeStream); + this.value = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/ARETURN.java b/src/main/java/haidnor/jvm/instruction/control/ARETURN.java new file mode 100644 index 0000000..2767dbf --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/ARETURN.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.JVMThreadHolder; + +public class ARETURN extends ReturnableInstruction { + + public ARETURN(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + // 弹出操作数栈中的值 + StackValue stackValue = frame.pop(); + // 将当前栈帧从 jvm 线程栈中弹出 + JVMThreadHolder.get().pop(); + // 将方法返回值压入前一个栈帧的操作数栈中 + Frame topFrame = JVMThreadHolder.get().peek(); + topFrame.push(stackValue); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/DRETURN.java b/src/main/java/haidnor/jvm/instruction/control/DRETURN.java new file mode 100644 index 0000000..cdfa6a8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/DRETURN.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.JVMThreadHolder; + +public class DRETURN extends ReturnableInstruction { + + public DRETURN(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + // 弹出操作数栈中的值 + StackValue stackValue = frame.pop(); + // 将当前栈帧从 jvm 线程栈中弹出 + JVMThreadHolder.get().pop(); + // 将方法返回值压入前一个栈帧的操作数栈中 + Frame topFrame = JVMThreadHolder.get().peek(); + topFrame.push(stackValue); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/FRETURN.java b/src/main/java/haidnor/jvm/instruction/control/FRETURN.java new file mode 100644 index 0000000..99f2b44 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/FRETURN.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.JVMThreadHolder; + +public class FRETURN extends ReturnableInstruction { + + public FRETURN(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + // 弹出操作数栈中的值 + StackValue stackValue = frame.pop(); + // 将当前栈帧从 jvm 线程栈中弹出 + JVMThreadHolder.get().pop(); + // 将方法返回值压入前一个栈帧的操作数栈中 + Frame topFrame = JVMThreadHolder.get().peek(); + topFrame.push(stackValue); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/IRETURN.java b/src/main/java/haidnor/jvm/instruction/control/IRETURN.java new file mode 100644 index 0000000..5299e66 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/IRETURN.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.JVMThreadHolder; + +public class IRETURN extends ReturnableInstruction { + + public IRETURN(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + // 弹出操作数栈中的值 + StackValue stackValue = frame.pop(); + // 将当前栈帧从 jvm 线程栈中弹出 + JVMThreadHolder.get().pop(); + // 将方法返回值压入前一个栈帧的操作数栈中 + Frame topFrame = JVMThreadHolder.get().peek(); + topFrame.push(stackValue); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/LOOKUPSWITCH.java b/src/main/java/haidnor/jvm/instruction/control/LOOKUPSWITCH.java new file mode 100644 index 0000000..87b7d6a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/LOOKUPSWITCH.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LOOKUPSWITCH extends Instruction { + + public LOOKUPSWITCH(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("LOOKUPSWITCH"); + } + + @Override + public void execute(Frame frame) { + throw new UnsupportedOperationException("LOOKUPSWITCH"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/LRETURN.java b/src/main/java/haidnor/jvm/instruction/control/LRETURN.java new file mode 100644 index 0000000..a0f58eb --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/LRETURN.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.JVMThreadHolder; + +public class LRETURN extends ReturnableInstruction { + + public LRETURN(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + // 弹出操作数栈中的值 + StackValue stackValue = frame.pop(); + // 将当前栈帧从 jvm 线程栈中弹出 + JVMThreadHolder.get().pop(); + // 将方法返回值压入前一个栈帧的操作数栈中 + Frame topFrame = JVMThreadHolder.get().peek(); + topFrame.push(stackValue); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/RET.java b/src/main/java/haidnor/jvm/instruction/control/RET.java new file mode 100644 index 0000000..18410e8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/RET.java @@ -0,0 +1,28 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * RET(Return)指令是 Java 虚拟机中的一条指令,用于从方法中返回并将控制流转移到调用该方法的位置。 + *

+ * RET 指令在早期版本的 Java 虚拟机中使用,但自从 Java SE 6 版本以后,它已经被废弃不再使用。取而代之的是通过 JSR 和 RET 指令的组合实现的子例程(subroutines)已经被新的字节码指令 invokedynamic 所取代。 + *

+ * RET 指令需要一个操作数,作为局部变量表(local variable table)中一个给定索引处的值。这个索引通常是由 JSR(Jump SubRoutine)指令记录的,JSR 指令在携带一个偏移量的情况下,会将指令执行的位置压入操作数栈,并跳转到指定的位置。RET 指令则使用这个记录的位置来返回。 + *

+ * 需要注意的是,由于 RET 指令被废弃,所以在现代的 Java 虚拟机中,解释器或即时编译器会将 RET 指令替换为其他的指令序列来实现相同的功能。 + */ +public class RET extends Instruction { + + public RET(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("RET"); + } + + @Override + public void execute(Frame frame) { + throw new UnsupportedOperationException("RET"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/control/RETURN.java b/src/main/java/haidnor/jvm/instruction/control/RETURN.java new file mode 100644 index 0000000..ea869fc --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/RETURN.java @@ -0,0 +1,18 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.JVMThreadHolder; + +public class RETURN extends ReturnableInstruction { + + public RETURN(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + JVMThreadHolder.get().pop(); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/ReturnableInstruction.java b/src/main/java/haidnor/jvm/instruction/control/ReturnableInstruction.java similarity index 74% rename from src/main/java/haidnor/jvm/instruction/ReturnableInstruction.java rename to src/main/java/haidnor/jvm/instruction/control/ReturnableInstruction.java index b5c91b3..5e00204 100644 --- a/src/main/java/haidnor/jvm/instruction/ReturnableInstruction.java +++ b/src/main/java/haidnor/jvm/instruction/control/ReturnableInstruction.java @@ -1,5 +1,6 @@ -package haidnor.jvm.instruction; +package haidnor.jvm.instruction.control; +import haidnor.jvm.instruction.Instruction; import haidnor.jvm.util.CodeStream; /** diff --git a/src/main/java/haidnor/jvm/instruction/control/TABLESWITCH.java b/src/main/java/haidnor/jvm/instruction/control/TABLESWITCH.java new file mode 100644 index 0000000..d4b71ef --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/control/TABLESWITCH.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.control; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class TABLESWITCH extends Instruction { + + public TABLESWITCH(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("TABLESWITCH"); + } + + @Override + public void execute(Frame frame) { + throw new UnsupportedOperationException("TABLESWITCH"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/D2F.java b/src/main/java/haidnor/jvm/instruction/conversions/D2F.java new file mode 100644 index 0000000..bbfc874 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/D2F.java @@ -0,0 +1,20 @@ + +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class D2F extends Instruction { + + public D2F(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double doubleVal = frame.popDouble(); + frame.pushFloat(Double.valueOf(doubleVal).floatValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/D2I.java b/src/main/java/haidnor/jvm/instruction/conversions/D2I.java new file mode 100644 index 0000000..94f5e44 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/D2I.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class D2I extends Instruction { + + public D2I(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double doubleVal = frame.popDouble(); + frame.pushInt(Double.valueOf(doubleVal).intValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/D2L.java b/src/main/java/haidnor/jvm/instruction/conversions/D2L.java new file mode 100644 index 0000000..1bba3f0 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/D2L.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class D2L extends Instruction { + + public D2L(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double doubleVal = frame.popDouble(); + frame.pushLong(Double.valueOf(doubleVal).longValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/F2D.java b/src/main/java/haidnor/jvm/instruction/conversions/F2D.java new file mode 100644 index 0000000..a4a0d77 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/F2D.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class F2D extends Instruction { + + public F2D(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float floatVal = frame.popFloat(); + frame.pushDouble(Float.valueOf(floatVal).doubleValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/F2I.java b/src/main/java/haidnor/jvm/instruction/conversions/F2I.java new file mode 100644 index 0000000..0a95939 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/F2I.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class F2I extends Instruction { + + public F2I(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float floatVal = frame.popFloat(); + frame.pushInt(Float.valueOf(floatVal).intValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/F2L.java b/src/main/java/haidnor/jvm/instruction/conversions/F2L.java new file mode 100644 index 0000000..cdadf34 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/F2L.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class F2L extends Instruction { + + public F2L(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float floatVal = frame.popFloat(); + frame.pushLong(Float.valueOf(floatVal).longValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/I2B.java b/src/main/java/haidnor/jvm/instruction/conversions/I2B.java new file mode 100644 index 0000000..1b84a80 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/I2B.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * JVM中的I2B指令是用于执行将整数类型(int)转换为字节类型(byte)的指令。该指令将一个int类型的数值从操作数栈中弹出,并将其转换为一个字节(byte)。 + * 然后,将转换后的字节值压入操作数栈顶。 + *

+ * byte 类型的数据是以 int 形式存在的,因此不需要做任何处理 + */ +public class I2B extends Instruction { + + public I2B(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/I2C.java b/src/main/java/haidnor/jvm/instruction/conversions/I2C.java new file mode 100644 index 0000000..04a9b08 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/I2C.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * char 类型的数据是以 int 形式存在的,因此不需要做任何处理 + */ +public class I2C extends Instruction { + + public I2C(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/I2D.java b/src/main/java/haidnor/jvm/instruction/conversions/I2D.java new file mode 100644 index 0000000..e62a3dd --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/I2D.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class I2D extends Instruction { + + public I2D(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int intVal = frame.popInt(); + frame.pushDouble(Integer.valueOf(intVal).doubleValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/I2F.java b/src/main/java/haidnor/jvm/instruction/conversions/I2F.java new file mode 100644 index 0000000..7c4daf5 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/I2F.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class I2F extends Instruction { + + public I2F(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int intVal = frame.popInt(); + frame.pushFloat(Integer.valueOf(intVal).floatValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/I2L.java b/src/main/java/haidnor/jvm/instruction/conversions/I2L.java new file mode 100644 index 0000000..6bb9ac8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/I2L.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class I2L extends Instruction { + + public I2L(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int intVal = frame.popInt(); + frame.pushLong(Integer.valueOf(intVal).longValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/I2S.java b/src/main/java/haidnor/jvm/instruction/conversions/I2S.java new file mode 100644 index 0000000..fe9cd1e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/I2S.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class I2S extends Instruction { + + public I2S(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int intVal = frame.popInt(); + short shortValue = Integer.valueOf(intVal).shortValue(); + frame.pushInt(((int) shortValue)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/L2D.java b/src/main/java/haidnor/jvm/instruction/conversions/L2D.java new file mode 100644 index 0000000..fd38919 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/L2D.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class L2D extends Instruction { + + public L2D(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long longVal = frame.popLong(); + frame.pushDouble(Long.valueOf(longVal).doubleValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/L2F.java b/src/main/java/haidnor/jvm/instruction/conversions/L2F.java new file mode 100644 index 0000000..ae4d084 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/L2F.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class L2F extends Instruction { + + public L2F(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long longVal = frame.popLong(); + frame.pushFloat(Long.valueOf(longVal).floatValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/conversions/L2I.java b/src/main/java/haidnor/jvm/instruction/conversions/L2I.java new file mode 100644 index 0000000..7e43556 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/conversions/L2I.java @@ -0,0 +1,19 @@ +package haidnor.jvm.instruction.conversions; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class L2I extends Instruction { + + public L2I(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long longVal = frame.popLong(); + frame.pushInt(Long.valueOf(longVal).intValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/extended/GOTO.java b/src/main/java/haidnor/jvm/instruction/extended/GOTO.java new file mode 100644 index 0000000..c723d79 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/extended/GOTO.java @@ -0,0 +1,33 @@ +package haidnor.jvm.instruction.extended; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode definitions in + * The Java Virtual Machine Specification + */ +public class GOTO extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public GOTO(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + super.setOffSet(offSet); + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } +} diff --git a/src/main/java/haidnor/jvm/instruction/extended/GOTO_W.java b/src/main/java/haidnor/jvm/instruction/extended/GOTO_W.java new file mode 100644 index 0000000..2042b7e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/extended/GOTO_W.java @@ -0,0 +1,27 @@ +package haidnor.jvm.instruction.extended; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class GOTO_W extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public GOTO_W(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readInt(this); + } + + @Override + public void execute(Frame frame) { + super.setOffSet(offSet); + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } +} diff --git a/src/main/java/haidnor/jvm/instruction/extended/IFNONNULL.java b/src/main/java/haidnor/jvm/instruction/extended/IFNONNULL.java new file mode 100644 index 0000000..eb7fc24 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/extended/IFNONNULL.java @@ -0,0 +1,33 @@ +package haidnor.jvm.instruction.extended; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFNONNULL extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFNONNULL(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if (v1.getValue() != null) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } +} diff --git a/src/main/java/haidnor/jvm/instruction/extended/IFNULL.java b/src/main/java/haidnor/jvm/instruction/extended/IFNULL.java new file mode 100644 index 0000000..1ee4e72 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/extended/IFNULL.java @@ -0,0 +1,33 @@ +package haidnor.jvm.instruction.extended; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class IFNULL extends Instruction { + /** + * 下次再执行的偏移量 + */ + private final int offSet; + + public IFNULL(CodeStream codeStream) { + super(codeStream); + this.offSet = codeStream.readShort(this); + } + + @Override + public void execute(Frame frame) { + StackValue v1 = frame.pop(); + if (v1.getValue() == null) { + super.setOffSet(offSet); + } else { + super.setOffSet(3); + } + } + + @Override + public String toString() { + return super.getIndex() + " " + this.getClass().getSimpleName() + " " + offSet; + } +} diff --git a/src/main/java/haidnor/jvm/instruction/extended/MULTIANEWARRAY.java b/src/main/java/haidnor/jvm/instruction/extended/MULTIANEWARRAY.java new file mode 100644 index 0000000..1833c97 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/extended/MULTIANEWARRAY.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.extended; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class MULTIANEWARRAY extends Instruction { + + public final int index; + public final int dimensions; + + public MULTIANEWARRAY(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedShort(this); + this.dimensions = codeStream.readUnsignedByte(this); + + throw new UnsupportedOperationException("MULTIANEWARRAY"); + } + + @Override + public void execute(Frame frame) { + throw new UnsupportedOperationException("MULTIANEWARRAY"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/extended/WIDE.java b/src/main/java/haidnor/jvm/instruction/extended/WIDE.java new file mode 100644 index 0000000..bbe453c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/extended/WIDE.java @@ -0,0 +1,40 @@ +package haidnor.jvm.instruction.extended; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.instruction.loads.*; +import haidnor.jvm.instruction.math.IINC; +import haidnor.jvm.instruction.stores.*; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class WIDE extends Instruction { + + private final Instruction instruction; + + public WIDE(CodeStream codeStream) { + super(codeStream); + int wideOpcode = codeStream.readShort(this); + + switch (wideOpcode) { + case 0x84 -> instruction = new IINC(codeStream); + case 0x15 -> instruction = new ILOAD(codeStream); + case 0x17 -> instruction = new FLOAD(codeStream); + case 0x19 -> instruction = new ALOAD(codeStream); + case 0x16 -> instruction = new LLOAD(codeStream); + case 0x18 -> instruction = new DLOAD(codeStream); + case 0x36 -> instruction = new ISTORE(codeStream); + case 0x38 -> instruction = new FSTORE(codeStream); + case 0x3a -> instruction = new ASTORE(codeStream); + case 0x37 -> instruction = new LSTORE(codeStream); + case 0x39 -> instruction = new DSTORE(codeStream); + case 0xa9 -> throw new UnsupportedOperationException(); // ret, ignore + default -> throw new UnsupportedOperationException(); + } + } + + @Override + public void execute(Frame frame) { + instruction.execute(frame); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/AALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/AALOAD.java new file mode 100644 index 0000000..020e8d1 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/AALOAD.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.rtda.InstanceArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class AALOAD extends Instruction { + + public AALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + InstanceArray array = (InstanceArray) frame.popRef(); + Instance item = array.items[index]; + frame.pushRef(item); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/ALOAD.java new file mode 100644 index 0000000..d5ad7a8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ALOAD.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + + +public class ALOAD extends Instruction { + + private final int index; + + public ALOAD(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + Object value = frame.slotGetRef(index); + frame.push(new StackValue(Const.T_OBJECT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ALOAD_0.java b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_0.java new file mode 100644 index 0000000..3aadccc --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_0.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class ALOAD_0 extends Instruction { + + public ALOAD_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Object value = frame.slotGetRef(0); + frame.push(new StackValue(Const.T_OBJECT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ALOAD_1.java b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_1.java new file mode 100644 index 0000000..83cd693 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_1.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class ALOAD_1 extends Instruction { + + public ALOAD_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Object value = frame.slotGetRef(1); + frame.push(new StackValue(Const.T_OBJECT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ALOAD_2.java b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_2.java new file mode 100644 index 0000000..8b52c1d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_2.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class ALOAD_2 extends Instruction { + + public ALOAD_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Object value = frame.slotGetRef(2); + frame.push(new StackValue(Const.T_OBJECT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ALOAD_3.java b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_3.java new file mode 100644 index 0000000..62e30c8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ALOAD_3.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class ALOAD_3 extends Instruction { + + public ALOAD_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Object value = frame.slotGetRef(3); + frame.push(new StackValue(Const.T_OBJECT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/BALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/BALOAD.java new file mode 100644 index 0000000..5e9bbf4 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/BALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class BALOAD extends Instruction { + + public BALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushInt(array.ints[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/CALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/CALOAD.java new file mode 100644 index 0000000..3ccc6a1 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/CALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class CALOAD extends Instruction { + + public CALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushInt(array.ints[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/DALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/DALOAD.java new file mode 100644 index 0000000..5db952e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/DALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class DALOAD extends Instruction { + + public DALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushDouble(array.doubles[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/DLOAD.java b/src/main/java/haidnor/jvm/instruction/loads/DLOAD.java new file mode 100644 index 0000000..5ab371a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/DLOAD.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + + +public class DLOAD extends Instruction { + + private final int index; + + public DLOAD(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + double value = frame.slotGetDouble(index); + frame.push(new StackValue(Const.T_DOUBLE, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/DLOAD_0.java b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_0.java new file mode 100644 index 0000000..d0c442d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_0.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DLOAD_0 extends Instruction { + + public DLOAD_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double value = frame.slotGetDouble(0); + frame.push(new StackValue(Const.T_DOUBLE, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/DLOAD_1.java b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_1.java new file mode 100644 index 0000000..e4c39ff --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_1.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DLOAD_1 extends Instruction { + + public DLOAD_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double value = frame.slotGetDouble(1); + frame.push(new StackValue(Const.T_DOUBLE, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/DLOAD_2.java b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_2.java new file mode 100644 index 0000000..18d1181 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_2.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DLOAD_2 extends Instruction { + + public DLOAD_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double value = frame.slotGetDouble(2); + frame.push(new StackValue(Const.T_DOUBLE, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/DLOAD_3.java b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_3.java new file mode 100644 index 0000000..02736c3 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/DLOAD_3.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DLOAD_3 extends Instruction { + + public DLOAD_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double value = frame.slotGetDouble(3); + frame.push(new StackValue(Const.T_DOUBLE, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/FALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/FALOAD.java new file mode 100644 index 0000000..f6e21d1 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/FALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class FALOAD extends Instruction { + + public FALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushFloat(array.floats[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/FLOAD.java b/src/main/java/haidnor/jvm/instruction/loads/FLOAD.java new file mode 100644 index 0000000..071824c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/FLOAD.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + + +public class FLOAD extends Instruction { + + private final int index; + + public FLOAD(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + float value = frame.slotGetFloat(index); + frame.push(new StackValue(Const.T_FLOAT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/FLOAD_0.java b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_0.java new file mode 100644 index 0000000..be08423 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_0.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FLOAD_0 extends Instruction { + + public FLOAD_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float value = frame.slotGetFloat(0); + frame.push(new StackValue(Const.T_FLOAT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/FLOAD_1.java b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_1.java new file mode 100644 index 0000000..e310aec --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_1.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FLOAD_1 extends Instruction { + + public FLOAD_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float value = frame.slotGetFloat(1); + frame.push(new StackValue(Const.T_FLOAT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/FLOAD_2.java b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_2.java new file mode 100644 index 0000000..656b3c5 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_2.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FLOAD_2 extends Instruction { + + public FLOAD_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float value = frame.slotGetFloat(2); + frame.push(new StackValue(Const.T_FLOAT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/FLOAD_3.java b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_3.java new file mode 100644 index 0000000..222489f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/FLOAD_3.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FLOAD_3 extends Instruction { + + public FLOAD_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float value = frame.slotGetFloat(3); + frame.push(new StackValue(Const.T_FLOAT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/IALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/IALOAD.java new file mode 100644 index 0000000..4abd5d2 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/IALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class IALOAD extends Instruction { + + public IALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushInt(array.ints[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ILOAD.java b/src/main/java/haidnor/jvm/instruction/loads/ILOAD.java new file mode 100644 index 0000000..2ab2a66 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ILOAD.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + + +public class ILOAD extends Instruction { + + private final int index; + + public ILOAD(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + int value = frame.slotGetInt(index); + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ILOAD_0.java b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_0.java new file mode 100644 index 0000000..52d0d84 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_0.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iload_n + */ +public class ILOAD_0 extends Instruction { + + public ILOAD_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int value = frame.slotGetInt(0); + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ILOAD_1.java b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_1.java new file mode 100644 index 0000000..83d2c68 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_1.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iload_n + */ +public class ILOAD_1 extends Instruction { + + public ILOAD_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int value = frame.slotGetInt(1); + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ILOAD_2.java b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_2.java new file mode 100644 index 0000000..8aca145 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_2.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iload_n + */ +public class ILOAD_2 extends Instruction { + + public ILOAD_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int value = frame.slotGetInt(2); + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/ILOAD_3.java b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_3.java new file mode 100644 index 0000000..6499455 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/ILOAD_3.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +/** + * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.iload_n + */ +public class ILOAD_3 extends Instruction { + + public ILOAD_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int value = frame.slotGetInt(3); + frame.push(new StackValue(Const.T_INT, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/LALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/LALOAD.java new file mode 100644 index 0000000..ade4a89 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/LALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class LALOAD extends Instruction { + + public LALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushLong(array.longs[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/LLOAD.java b/src/main/java/haidnor/jvm/instruction/loads/LLOAD.java new file mode 100644 index 0000000..e19afcc --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/LLOAD.java @@ -0,0 +1,25 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + + +public class LLOAD extends Instruction { + + private final int index; + + public LLOAD(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + long value = frame.slotGetLong(index); + frame.push(new StackValue(Const.T_LONG, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/LLOAD_0.java b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_0.java new file mode 100644 index 0000000..a5c0104 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_0.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LLOAD_0 extends Instruction { + + public LLOAD_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long value = frame.slotGetLong(0); + frame.push(new StackValue(Const.T_LONG, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/LLOAD_1.java b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_1.java new file mode 100644 index 0000000..4a15dbc --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_1.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LLOAD_1 extends Instruction { + + public LLOAD_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long value = frame.slotGetLong(1); + frame.push(new StackValue(Const.T_LONG, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/LLOAD_2.java b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_2.java new file mode 100644 index 0000000..fb16f36 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_2.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LLOAD_2 extends Instruction { + + public LLOAD_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long value = frame.slotGetLong(2); + frame.push(new StackValue(Const.T_LONG, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/LLOAD_3.java b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_3.java new file mode 100644 index 0000000..945b037 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/LLOAD_3.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LLOAD_3 extends Instruction { + + public LLOAD_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long value = frame.slotGetLong(3); + frame.push(new StackValue(Const.T_LONG, value)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/loads/SALOAD.java b/src/main/java/haidnor/jvm/instruction/loads/SALOAD.java new file mode 100644 index 0000000..a51a2fa --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/loads/SALOAD.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.loads; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + + +public class SALOAD extends Instruction { + + public SALOAD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + frame.pushInt(array.ints[index]); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/DADD.java b/src/main/java/haidnor/jvm/instruction/math/DADD.java new file mode 100644 index 0000000..9a3544d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/DADD.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DADD extends Instruction { + + public DADD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + double result = (double) value1.getValue() + (double) value2.getValue(); + frame.push(new StackValue(Const.T_DOUBLE, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/DDIV.java b/src/main/java/haidnor/jvm/instruction/math/DDIV.java new file mode 100644 index 0000000..7204e4f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/DDIV.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DDIV extends Instruction { + + public DDIV(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + double result = (double) value1.getValue() / (double) value2.getValue(); + frame.push(new StackValue(Const.T_DOUBLE, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/DMUL.java b/src/main/java/haidnor/jvm/instruction/math/DMUL.java new file mode 100644 index 0000000..482e0a0 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/DMUL.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DMUL extends Instruction { + + public DMUL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + double result = (double) value1.getValue() * (double) value2.getValue(); + frame.push(new StackValue(Const.T_DOUBLE, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/DNEG.java b/src/main/java/haidnor/jvm/instruction/math/DNEG.java new file mode 100644 index 0000000..3b91a4d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/DNEG.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DNEG extends Instruction { + + public DNEG(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue stackValue = frame.pop(); + double value = (double) stackValue.getValue(); + double tmp = -value; + frame.push(new StackValue(Const.T_DOUBLE, tmp)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/DREM.java b/src/main/java/haidnor/jvm/instruction/math/DREM.java new file mode 100644 index 0000000..5eab3b2 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/DREM.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DREM extends Instruction { + + public DREM(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + double result = (double) value1.getValue() % (double) value2.getValue(); + frame.push(new StackValue(Const.T_DOUBLE, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/DSUB.java b/src/main/java/haidnor/jvm/instruction/math/DSUB.java new file mode 100644 index 0000000..553af3b --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/DSUB.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class DSUB extends Instruction { + + public DSUB(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + double result = (double) value1.getValue() - (double) value2.getValue(); + frame.push(new StackValue(Const.T_DOUBLE, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/FADD.java b/src/main/java/haidnor/jvm/instruction/math/FADD.java new file mode 100644 index 0000000..e902127 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/FADD.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FADD extends Instruction { + + public FADD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + float result = (float) value1.getValue() + (float) value2.getValue(); + frame.push(new StackValue(Const.T_FLOAT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/FDIV.java b/src/main/java/haidnor/jvm/instruction/math/FDIV.java new file mode 100644 index 0000000..6caa0e7 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/FDIV.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FDIV extends Instruction { + + public FDIV(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + float result = (float) value1.getValue() / (float) value2.getValue(); + frame.push(new StackValue(Const.T_FLOAT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/FMUL.java b/src/main/java/haidnor/jvm/instruction/math/FMUL.java new file mode 100644 index 0000000..e6b4c97 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/FMUL.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FMUL extends Instruction { + + public FMUL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + float result = (float) value1.getValue() * (float) value2.getValue(); + frame.push(new StackValue(Const.T_FLOAT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/FNEG.java b/src/main/java/haidnor/jvm/instruction/math/FNEG.java new file mode 100644 index 0000000..789a17f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/FNEG.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FNEG extends Instruction { + + public FNEG(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue stackValue = frame.pop(); + float value = (float) stackValue.getValue(); + float tmp = -value; + frame.push(new StackValue(Const.T_FLOAT, tmp)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/FREM.java b/src/main/java/haidnor/jvm/instruction/math/FREM.java new file mode 100644 index 0000000..e21b2fa --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/FREM.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FREM extends Instruction { + + public FREM(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + float result = (float) value1.getValue() % (float) value2.getValue(); + frame.push(new StackValue(Const.T_FLOAT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/FSUB.java b/src/main/java/haidnor/jvm/instruction/math/FSUB.java new file mode 100644 index 0000000..201df87 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/FSUB.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class FSUB extends Instruction { + + public FSUB(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + float result = (float) value1.getValue() - (float) value2.getValue(); + frame.push(new StackValue(Const.T_FLOAT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IADD.java b/src/main/java/haidnor/jvm/instruction/math/IADD.java new file mode 100644 index 0000000..dc3120d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IADD.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class IADD extends Instruction { + + public IADD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + int result = (int) value1.getValue() + (int) value2.getValue(); + frame.push(new StackValue(Const.T_INT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IAND.java b/src/main/java/haidnor/jvm/instruction/math/IAND.java new file mode 100644 index 0000000..396420f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IAND.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class IAND extends Instruction { + + public IAND(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Integer v2 = frame.popInt(); + Integer v1 = frame.popInt(); + int val = v1 & v2; + frame.pushInt(val); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IDIV.java b/src/main/java/haidnor/jvm/instruction/math/IDIV.java new file mode 100644 index 0000000..e8a5c82 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IDIV.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class IDIV extends Instruction { + + public IDIV(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + int result = (int) value1.getValue() / (int) value2.getValue(); + frame.push(new StackValue(Const.T_INT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IINC.java b/src/main/java/haidnor/jvm/instruction/math/IINC.java new file mode 100644 index 0000000..8dd1958 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IINC.java @@ -0,0 +1,37 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * Java VM opcode. + * + * @see Opcode definitions in + * The Java Virtual Machine Specification + */ +public class IINC extends Instruction { + + /** + * 局部变量表中需要被自增元素的索引 + */ + public final int index; + + /** + * 自增值 + */ + public final int increment; + + public IINC(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + this.increment = codeStream.readByte(this); + } + + @Override + public void execute(Frame frame) { + int value = frame.slotGetInt(index); + frame.slotSetInt(index, value + increment); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IMUL.java b/src/main/java/haidnor/jvm/instruction/math/IMUL.java new file mode 100644 index 0000000..df5ff2d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IMUL.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class IMUL extends Instruction { + + public IMUL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + int result = (int) value1.getValue() * (int) value2.getValue(); + frame.push(new StackValue(Const.T_INT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/INEG.java b/src/main/java/haidnor/jvm/instruction/math/INEG.java new file mode 100644 index 0000000..f66dc08 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/INEG.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class INEG extends Instruction { + + public INEG(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue stackValue = frame.pop(); + int value = (int) stackValue.getValue(); + int tmp = -value; + frame.push(new StackValue(Const.T_INT, tmp)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IOR.java b/src/main/java/haidnor/jvm/instruction/math/IOR.java new file mode 100644 index 0000000..0202bb3 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IOR.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class IOR extends Instruction { + + public IOR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int v2 = frame.popInt(); + int v1 = frame.popInt(); + frame.pushInt(v1 | v2); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IREM.java b/src/main/java/haidnor/jvm/instruction/math/IREM.java new file mode 100644 index 0000000..8cad36a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IREM.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class IREM extends Instruction { + + public IREM(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + int result = (int) value1.getValue() % (int) value2.getValue(); + frame.push(new StackValue(Const.T_INT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/ISHL.java b/src/main/java/haidnor/jvm/instruction/math/ISHL.java new file mode 100644 index 0000000..d9273b5 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/ISHL.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class ISHL extends Instruction { + + public ISHL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int v2 = frame.popInt(); + int v1 = frame.popInt(); + int s = v2 & 0x1f; + int ret = v1 << s; + frame.pushInt(ret); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/ISHR.java b/src/main/java/haidnor/jvm/instruction/math/ISHR.java new file mode 100644 index 0000000..ae36c0d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/ISHR.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class ISHR extends Instruction { + + public ISHR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int v2 = frame.popInt(); + int v1 = frame.popInt(); + int s = v2 & 0x1f; + int ret = v1 >> s; + frame.pushInt(ret); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/ISUB.java b/src/main/java/haidnor/jvm/instruction/math/ISUB.java new file mode 100644 index 0000000..197ec04 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/ISUB.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class ISUB extends Instruction { + + public ISUB(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + int result = (int) value1.getValue() - (int) value2.getValue(); + frame.push(new StackValue(Const.T_INT, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IUSHR.java b/src/main/java/haidnor/jvm/instruction/math/IUSHR.java new file mode 100644 index 0000000..7f0c822 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IUSHR.java @@ -0,0 +1,37 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +/** + * JVM中的IUSHR指令是用于执行无符号右移操作的指令。该指令将两个整数值从操作数栈中弹出, + * 然后将第一个操作数的位表示向右移动第二个操作数指定的位数,移位过程中高位用零填充。最后,将结果压入操作数栈中。 + * + * 在Java虚拟机规范中,IUSHR指令的操作码为0x7C,它属于逻辑指令家族(logical instructions)。 + * 这个指令通常需用到无符号数值在位级上的运算,因此它主要用于一些特定的计算和算法中。 + * + * 需要注意的是,IUSHR指令只适用于int类型的数据。如果操作数是long类型,则需要使用LUSHR指令进行无符号右移操作。 + */ +public class IUSHR extends Instruction { + + public IUSHR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int v2 = frame.popInt(); + int v1 = frame.popInt(); + int s = v2 & 0x1f; + + if (v1 >= 0) { + int ret = v1 >> s; + frame.pushInt(ret); + return; + } + int ret = (v1 >> s) + (2 << ~s); + frame.pushInt(ret); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/IXOR.java b/src/main/java/haidnor/jvm/instruction/math/IXOR.java new file mode 100644 index 0000000..f6aceba --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/IXOR.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class IXOR extends Instruction { + + public IXOR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + final int v2 = frame.popInt(); + final int v1 = frame.popInt(); + frame.pushInt(v1 ^ v2); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LADD.java b/src/main/java/haidnor/jvm/instruction/math/LADD.java new file mode 100644 index 0000000..62b2f03 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LADD.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LADD extends Instruction { + + public LADD(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + long result = (long) value1.getValue() + (long) value2.getValue(); + frame.push(new StackValue(Const.T_LONG, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LAND.java b/src/main/java/haidnor/jvm/instruction/math/LAND.java new file mode 100644 index 0000000..06988b9 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LAND.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LAND extends Instruction { + + public LAND(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long a1 = frame.popLong(); + long a2 = frame.popLong(); + frame.pushLong(a2 & a1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LDIV.java b/src/main/java/haidnor/jvm/instruction/math/LDIV.java new file mode 100644 index 0000000..16772cf --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LDIV.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LDIV extends Instruction { + + public LDIV(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + long result = (long) value1.getValue() / (long) value2.getValue(); + frame.push(new StackValue(Const.T_LONG, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LMUL.java b/src/main/java/haidnor/jvm/instruction/math/LMUL.java new file mode 100644 index 0000000..1bc1d7e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LMUL.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LMUL extends Instruction { + + public LMUL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + long result = (long) value1.getValue() * (long) value2.getValue(); + frame.push(new StackValue(Const.T_LONG, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LNEG.java b/src/main/java/haidnor/jvm/instruction/math/LNEG.java new file mode 100644 index 0000000..53922c6 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LNEG.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LNEG extends Instruction { + + public LNEG(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue stackValue = frame.pop(); + long value = (long) stackValue.getValue(); + long tmp = -value; + frame.push(new StackValue(Const.T_LONG, tmp)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LOR.java b/src/main/java/haidnor/jvm/instruction/math/LOR.java new file mode 100644 index 0000000..024a15d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LOR.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LOR extends Instruction { + + public LOR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Long v2 = frame.popLong(); + Long v1 = frame.popLong(); + frame.pushLong(v1 | v2); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LREM.java b/src/main/java/haidnor/jvm/instruction/math/LREM.java new file mode 100644 index 0000000..68a4a50 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LREM.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LREM extends Instruction { + + public LREM(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + long result = (long) value1.getValue() % (long) value2.getValue(); + frame.push(new StackValue(Const.T_LONG, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LSHL.java b/src/main/java/haidnor/jvm/instruction/math/LSHL.java new file mode 100644 index 0000000..8177ad2 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LSHL.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LSHL extends Instruction { + + public LSHL(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int v2 = frame.popInt(); + long v1 = frame.popLong(); + int s = v2 & 0x1f; + long ret = v1 << s; + frame.pushLong(ret); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LSHR.java b/src/main/java/haidnor/jvm/instruction/math/LSHR.java new file mode 100644 index 0000000..7837209 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LSHR.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LSHR extends Instruction { + + public LSHR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + final int v2 = frame.popInt(); + final long v1 = frame.popLong(); + frame.pushLong(v1 >> v2); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LSUB.java b/src/main/java/haidnor/jvm/instruction/math/LSUB.java new file mode 100644 index 0000000..8f3986f --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LSUB.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.bcel.Const; + +public class LSUB extends Instruction { + + public LSUB(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value2 = frame.pop(); + StackValue value1 = frame.pop(); + long result = (long) value1.getValue() - (long) value2.getValue(); + frame.push(new StackValue(Const.T_LONG, result)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LUSHR.java b/src/main/java/haidnor/jvm/instruction/math/LUSHR.java new file mode 100644 index 0000000..fbe63a9 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LUSHR.java @@ -0,0 +1,28 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LUSHR extends Instruction { + + public LUSHR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int v2 = frame.popInt(); + long v1 = frame.popLong(); + int s = v2 & 0x3f; + + if (v1 >= 0) { + long ret = v1 >> s; + frame.pushLong(ret); + return; + } + long ret = (v1 >> s) + (2L << ~s); + frame.pushLong(ret); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/math/LXOR.java b/src/main/java/haidnor/jvm/instruction/math/LXOR.java new file mode 100644 index 0000000..cb13220 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/math/LXOR.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.math; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LXOR extends Instruction { + + public LXOR(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long v2 = frame.popLong(); + long v1 = frame.popLong(); + frame.pushLong(v1 ^ v2); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java b/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java new file mode 100644 index 0000000..6f91e90 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java @@ -0,0 +1,41 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.JavaClass; +import haidnor.jvm.bcel.classfile.Utility; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.rtda.InstanceArray; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class ANEWARRAY extends Instruction { + + private final int constantClassIndex; + + public ANEWARRAY(CodeStream codeStream) { + super(codeStream); + this.constantClassIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + String className = frame.getJavaMethod().getConstantPool().constantClass_ClassName(constantClassIndex); + + JavaClass klass = Metaspace.getJavaClass(Utility.compactClassName(className)); + if (klass == null) { + // 如果在元空间中找不到已加载的类,则开始进行类加载流程 + klass = frame.getJavaClass().getJVMClassLoader().loadWithClassPath(className); + } + int size = frame.popInt(); + Instance[] items = new Instance[size]; + InstanceArray instanceArray = new InstanceArray(klass, items); + + frame.push(new StackValue(Const.T_OBJECT, instanceArray)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/ARRAYLENGTH.java b/src/main/java/haidnor/jvm/instruction/references/ARRAYLENGTH.java new file mode 100644 index 0000000..0b5ca55 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/ARRAYLENGTH.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.ArrayInstance; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class ARRAYLENGTH extends Instruction { + + public ARRAYLENGTH(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ArrayInstance array = (ArrayInstance) frame.popRef(); + frame.pushInt(array.size); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/ATHROW.java b/src/main/java/haidnor/jvm/instruction/references/ATHROW.java new file mode 100644 index 0000000..fc5a2c0 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/ATHROW.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class ATHROW extends Instruction { + + public ATHROW(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue pop = frame.pop(); + throw (Exception) pop.getValue(); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/CHECKCAST.java b/src/main/java/haidnor/jvm/instruction/references/CHECKCAST.java new file mode 100644 index 0000000..15a4874 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/CHECKCAST.java @@ -0,0 +1,24 @@ + +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class CHECKCAST extends Instruction { + + private final int constantClassIndex; + + public CHECKCAST(CodeStream codeStream) { + super(codeStream); + this.constantClassIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + // 暂时不支持 + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/GETFIELD.java b/src/main/java/haidnor/jvm/instruction/references/GETFIELD.java new file mode 100644 index 0000000..9c9994c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/GETFIELD.java @@ -0,0 +1,52 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.classfile.ConstantPool; +import haidnor.jvm.bcel.classfile.JavaField; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class GETFIELD extends Instruction { + + private final int constantFieldrefIndex; + + public GETFIELD(CodeStream codeStream) { + super(codeStream); + this.constantFieldrefIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + String filedName = constantPool.getFieldName(constantFieldrefIndex); + String fieldSignature = constantPool.getFieldSignature(constantFieldrefIndex); + + Instance instanceRef = frame.popRef(); + JavaField field = instanceRef.getField(filedName, fieldSignature); + switch (field.getSignature()) { + case "Z": + case "C": + case "B": + case "S": + case "I": + frame.pushInt((int) field.getValue()); + break; + case "J": + frame.pushLong((long) field.getValue()); + break; + case "F": + frame.pushFloat((float) field.getValue()); + break; + case "D": + frame.pushDouble((double) field.getValue()); + break; + default: // ref + frame.pushRef(field.getValue()); + break; + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java b/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java new file mode 100644 index 0000000..6bc849c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java @@ -0,0 +1,51 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +import java.lang.reflect.Field; + +/** + * 获取字段符号引用指定的对象或者值(类的静态字段 static 修饰),并将其压入操作数栈 + * + * @author wang xiang + */ +public class GETSTATIC extends Instruction { + + private final int constantFieldrefIndex; + + public GETSTATIC(CodeStream codeStream) { + super(codeStream); + this.constantFieldrefIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + ConstantFieldref constFieldref = constantPool.getConstant(constantFieldrefIndex); + // 动态链接. 找到字段所属的 Java 类 + String className = constantPool.constantFieldref_ClassName(constFieldref); + // 动态链接. 找到字段的名字 + String fieldName = constantPool.getFieldName(constFieldref); + // 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数. + + if (className.startsWith("java/")) { + Class clazz = Class.forName(className.replace('/', '.')); + Field field = clazz.getField(fieldName); + Object staticFiledValue = field.get(null); // 获取静态字段上的值 + frame.push(new StackValue(Const.T_OBJECT, staticFiledValue)); + } else { + JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className)); + JavaField staticField = javaClass.getStaticField(fieldName); + frame.push(new StackValue(Const.T_OBJECT, staticField.getValue())); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java b/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java new file mode 100644 index 0000000..6e00d80 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java @@ -0,0 +1,78 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.ConstantPool; +import haidnor.jvm.bcel.classfile.JavaClass; +import haidnor.jvm.bcel.classfile.Utility; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * @author wang xiang + */ +public class INSTANCEOF extends Instruction { + + private final int constantClassIndex; + + public INSTANCEOF(CodeStream codeStream) { + super(codeStream); + this.constantClassIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + + String className = constantPool.constantClass_ClassName(constantClassIndex); + className = Utility.compactClassName(className); + + StackValue stackValue = frame.pop(); + Object obj = stackValue.getValue(); + Class objClass = obj.getClass(); + + if (obj instanceof Instance instance) { + boolean result = findClassFromSuper(instance.getJavaClass(), className); + if (!result) { + result = findClassFromInterface(instance.getJavaClass(), className); + } + if (result) { + frame.push(new StackValue(Const.T_INT, 1)); + } else { + frame.push(new StackValue(Const.T_INT, 0)); + } + } else { + if (Class.forName(className).isAssignableFrom(objClass)) { + frame.push(new StackValue(Const.T_INT, 1)); + } else { + frame.push(new StackValue(Const.T_INT, 0)); + } + } + } + + public boolean findClassFromSuper(JavaClass javaClass, String className) throws ClassNotFoundException { + if (javaClass.getClassName().equals(className)) { + return true; + } + for (JavaClass superClass : javaClass.getSuperClasses()) { + if (superClass.getClassName().equals(className)) { + return true; + } + } + return false; + } + + public boolean findClassFromInterface(JavaClass javaClass, String className) throws ClassNotFoundException { + for (JavaClass anInterface : javaClass.getInterfaces()) { + if (anInterface.getClassName().equals(className)) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/INVOKEDYNAMIC.java b/src/main/java/haidnor/jvm/instruction/references/INVOKEDYNAMIC.java new file mode 100644 index 0000000..5dc978a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKEDYNAMIC.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class INVOKEDYNAMIC extends Instruction { + + public INVOKEDYNAMIC(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("INVOKEDYNAMIC"); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + throw new UnsupportedOperationException("INVOKEDYNAMIC"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java b/src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java new file mode 100644 index 0000000..f04516a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java @@ -0,0 +1,146 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.classloader.JVMClassLoader; +import haidnor.jvm.core.JavaExecutionEngine; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.SignatureUtil; +import lombok.SneakyThrows; + +import java.lang.reflect.Method; +import java.util.Objects; + + +public class INVOKEINTERFACE extends Instruction { + + private final int constantMethodrefIndex; + + public final int count; + + public final int zero; + + public INVOKEINTERFACE(CodeStream codeStream) { + super(codeStream); + this.constantMethodrefIndex = codeStream.readUnsignedShort(this); + this.count = codeStream.readUnsignedByte(this); + this.zero = codeStream.readUnsignedByte(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + + ConstantInterfaceMethodref interfaceMethodref = constantPool.getConstant(constantMethodrefIndex); + + int classIndex = interfaceMethodref.getClassIndex(); + String interfaceName = constantPool.constantClass_ClassName(classIndex); + + int nameAndTypeIndex = interfaceMethodref.getNameAndTypeIndex(); + String methodName = constantPool.constantNameAndType_name(nameAndTypeIndex); + String methodSignature = constantPool.constantNameAndType_signature(nameAndTypeIndex); + + // 系统类反射 自定义类另外处理 + if (interfaceName.startsWith("java/")) { + // 解析方法签名得到方法的返回类型 + String returnType = Utility.methodSignatureReturnType(methodSignature, false); + // 执行方法的参数列表 + Class[] parameterTypeArr = SignatureUtil.getParameterTypeArr(methodSignature); + // 执行方法的参数值 + Object[] args = frame.popStacksValue(parameterTypeArr.length); + // 将特定的参数转换为基本类型 + for (int i = 0; i < parameterTypeArr.length; i++) { + Class clazz = parameterTypeArr[i]; + if (clazz.getName().equals("boolean")) { // boolean 存储方式为 int 类型 + int booleanFlag = (int) args[i]; + args[i] = booleanFlag == 1; + } else if (clazz.getName().equals("char")) { // char 存储方式为 + int charInt = (int) args[i]; + char c = (char) charInt; + args[i] = c; + } + } + + StackValue stackValue = frame.pop(); + Object obj = stackValue.getValue(); + Method method = obj.getClass().getMethod(methodName, parameterTypeArr); + method.setAccessible(true); + Object value = method.invoke(obj, args); + if (!Objects.equals(Const.getTypeName(Const.T_VOID), returnType)) { // void 调用的方法无返回值 + frame.push(new StackValue(Const.T_OBJECT, value)); + } + } + // 调用自定义类的方法 + else { + JavaClass interfaceKlass = Metaspace.getJavaClass(Utility.compactClassName(interfaceName)); + if (interfaceKlass == null) { + JVMClassLoader classLoader = frame.getJavaClass().getJVMClassLoader(); + classLoader.loadWithClassPath(interfaceName); + } + + StackValue stackValue = frame.peek(); + Instance instance = (Instance) stackValue.getValue(); + + // 按照继承关系从下往上找实现的方法 (实现多态) + JavaMethod method = getMethod(instance.getJavaClass(), methodSignature, methodName); + // 从接口找方法 JDK8. interface default() + if (method == null) { + method = getMethodFromInterface(instance.getJavaClass(), methodSignature, methodName); + } + if (method == null) { + throw new AbstractMethodError(); + } + JavaExecutionEngine.callMethod(frame, method); + } + } + + /** + * 递归查找方法, 如果子类没有实现方法则向父类查找 + */ + private static JavaMethod getMethod(JavaClass javaClass, String methodSignature, String methodName) throws ClassNotFoundException { + JavaMethod m = null; + for (JavaMethod method : javaClass.getMethods()) { + if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { + m = method; + } + } + if (m != null) { + return m; + } + if (javaClass.getSuperClass() == null) { + return null; + } + return getMethod(javaClass.getSuperClass(), methodSignature, methodName); + } + + private static JavaMethod getMethodFromInterface(JavaClass javaClass, String methodSignature, String methodName) throws ClassNotFoundException { + JavaClass[] interfaces = javaClass.getInterfaces(); + if (interfaces.length == 0) { + for (JavaMethod method : javaClass.getMethods()) { + if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { + return method; + } + } + } + for (JavaClass interfaceJavaClass : interfaces) { + for (JavaMethod method : interfaceJavaClass.getMethods()) { + if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { + return method; + } + } + if (interfaceJavaClass.getInterfaces() != null) { + for (JavaClass classInterface : interfaceJavaClass.getInterfaces()) { + return getMethodFromInterface(classInterface, methodSignature, methodName); + } + } + } + return null; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/INVOKESPECIAL.java b/src/main/java/haidnor/jvm/instruction/references/INVOKESPECIAL.java new file mode 100644 index 0000000..16f8106 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKESPECIAL.java @@ -0,0 +1,78 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.classloader.JVMClassLoader; +import haidnor.jvm.core.JavaExecutionEngine; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.SignatureUtil; +import lombok.SneakyThrows; + +/** + * 调用一些需要特殊处理的实例方法,包括构造器方法,私有方法,父类方法,这些方法都是静态绑定的,不会在调用时进行动态分配 + */ +public class INVOKESPECIAL extends Instruction { + + private final int constantMethodrefIndex; + + public INVOKESPECIAL(CodeStream codeStream) { + super(codeStream); + this.constantMethodrefIndex = codeStream.readUnsignedShort(this); + } + + @SneakyThrows + @Override + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + ConstantMethodref methodref = constantPool.getConstant(constantMethodrefIndex); + + String className = constantPool.constantMethodref_ClassName(methodref); + String methodName = constantPool.constantMethodref_MethodName(methodref); + String methodSignature = constantPool.constantMethodref_MethodSignature(methodref); + + JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className)); + if (javaClass == null) { + JVMClassLoader classLoader = frame.getJavaClass().getJVMClassLoader(); + javaClass = classLoader.loadWithClassPath(className); + } + + if (className.startsWith("java/")) { + // 执行 RT.jar 中 Java 对象构造方法的时候创建java对象 + if (methodName.equals("")) { + // 执行方法的参数列表 + Class[] parameterTypeArr = SignatureUtil.getParameterTypeArr(methodSignature); + // 执行方法的参数值 + Object[] args = frame.popStacksValue(parameterTypeArr.length); + // 将特定的参数转换为基本类型 + for (int i = 0; i < parameterTypeArr.length; i++) { + Class clazz = parameterTypeArr[i]; + if (clazz.getName().equals("boolean")) { // boolean 存储方式为 int 类型 + int booleanFlag = (int) args[i]; + args[i] = booleanFlag == 1; + } else if (clazz.getName().equals("char")) { // char 存储方式为 + int charInt = (int) args[i]; + char c = (char) charInt; + args[i] = c; + } + } + Object javaObj = Class.forName(Utility.compactClassName(className,false)).getDeclaredConstructor(parameterTypeArr).newInstance(args); + frame.push(new StackValue(Const.T_OBJECT, javaObj)); // NEW + frame.push(new StackValue(Const.T_OBJECT, javaObj)); // DUP + return; + } + } + + for (JavaMethod method : javaClass.getMethods()) { + if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { + JavaExecutionEngine.callMethod(frame, method); + break; + } + } + } + + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/INVOKESTATIC.java b/src/main/java/haidnor/jvm/instruction/references/INVOKESTATIC.java new file mode 100644 index 0000000..601c953 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKESTATIC.java @@ -0,0 +1,91 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.core.JavaExecutionEngine; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.SignatureUtil; +import lombok.SneakyThrows; + +import java.util.Objects; + +/** + * 调用 static 静态方法.这是静态绑定的 + */ +public class INVOKESTATIC extends Instruction { + + private final int constantIndex; + + public INVOKESTATIC(CodeStream codeStream) { + super(codeStream); + this.constantIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + + String className; + String methodName; + String methodSignature; + + Constant constant = constantPool.getConstant(constantIndex); + if (constant instanceof ConstantMethodref constantMethodref) { + className = constantPool.constantMethodref_ClassName(constantMethodref); + methodName = constantPool.constantMethodref_MethodName(constantMethodref); + methodSignature = constantPool.constantMethodref_MethodSignature(constantMethodref); + + } else if (constant instanceof ConstantInterfaceMethodref interfaceMethodref) { + className = constantPool.constantInterfaceMethodref_ClassName(interfaceMethodref); + methodName = constantPool.constantInterfaceMethodref_MethodName(interfaceMethodref); + methodSignature = constantPool.constantInterfaceMethodref_MethodSignature(interfaceMethodref); + } else { + throw new ClassCastException(); + } + + // 系统类反射 自定义类另外处理 + if (className.startsWith("java/")) { + // 解析方法签名得到方法的返回类型 + String returnType = Utility.methodSignatureReturnType(methodSignature, false); + Class[] parameterTypeArr = SignatureUtil.getParameterTypeArr(methodSignature); + Object[] stacksValueArr = frame.popStacksValue(parameterTypeArr.length); + for (int i = 0; i < parameterTypeArr.length; i++) { + Class aClass = parameterTypeArr[i]; + if (aClass.getName().equals("boolean")) { + int booleanFlag = (int) stacksValueArr[i]; + stacksValueArr[i] = booleanFlag == 1; + } + } + + Class javaClass = Class.forName(Utility.compactClassName(className, false)); + java.lang.reflect.Method method = javaClass.getMethod(methodName, parameterTypeArr); + method.setAccessible(true); + Object value = method.invoke(null, stacksValueArr); + if (!Objects.equals(Const.getTypeName(Const.T_VOID), returnType)) { // void 调用的方法无返回值 + frame.push(new StackValue(Const.T_OBJECT, value)); + } + } + // 自定义类的方法 + else { + JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className)); + // 调用静态方法时加载类 + if (javaClass == null) { + javaClass = frame.getJavaClass().getJVMClassLoader().loadWithClassPath(className); + } + for (JavaMethod method : javaClass.getMethods()) { + if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { + JavaExecutionEngine.callMethod(frame, method); + break; + } + } + + } + + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java b/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java new file mode 100644 index 0000000..427c682 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java @@ -0,0 +1,108 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.classloader.JVMClassLoader; +import haidnor.jvm.core.JavaExecutionEngine; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +import java.lang.reflect.Method; +import java.util.Objects; + +/** + * 调用对象实例方法,根据对象的实际类型进行分派(虚方法分派),支持多态 + */ +public class INVOKEVIRTUAL extends Instruction { + + private final int constantMethodrefIndex; + + public INVOKEVIRTUAL(CodeStream codeStream) { + super(codeStream); + this.constantMethodrefIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + ConstantMethodref methodRef = constantPool.getConstant(constantMethodrefIndex); + String className = methodRef.getClassName(); + String methodName = methodRef.getMethodName(); + String methodSignature = methodRef.getMethodSignature(); + + // 系统类反射 自定义类另外处理 + if (className.startsWith("java/")) { + + // 执行方法的参数列表 + Class[] parameterTypeArr = methodRef.getParameterTypeArr(); + // 执行方法的参数值 + Object[] args = frame.popStacksValue(parameterTypeArr.length); + // 将特定的参数转换为基本类型 + for (int i = 0; i < parameterTypeArr.length; i++) { + Class clazz = parameterTypeArr[i]; + if (clazz.getName().equals("boolean")) { // boolean 存储方式为 int 类型 + int booleanFlag = (int) args[i]; + args[i] = booleanFlag == 1; + } else if (clazz.getName().equals("char")) { // char 存储方式为 + int charInt = (int) args[i]; + char c = (char) charInt; + args[i] = c; + } + } + + StackValue stackValue = frame.pop(); + Object obj = stackValue.getValue(); + Method method = obj.getClass().getMethod(methodName, parameterTypeArr); + method.setAccessible(true); + Object value = method.invoke(obj, args); + + // 解析方法签名得到方法的返回类型 + String returnType = methodRef.getReturnType(); + // void 调用的方法无返回值 + if (!Objects.equals(Const.getTypeName(Const.T_VOID), returnType)) { + frame.push(new StackValue(Const.T_OBJECT, value)); + } + } + // 调用自定义类的方法 + else { + JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className)); + if (javaClass == null) { + JVMClassLoader classLoader = frame.getJavaClass().getJVMClassLoader(); + javaClass = classLoader.loadWithClassPath(className); + } + + // 按照继承关系从下往上找实现的方法 (实现多态) + JavaMethod method = getMethod(javaClass, methodSignature, methodName); + if (method == null) { + throw new AbstractMethodError(); + } + JavaExecutionEngine.callMethod(frame, method); + } + } + + /** + * 递归查找方法, 如果子类没有实现方法则向父类查找 + */ + @SneakyThrows + private static JavaMethod getMethod(JavaClass javaClass, String methodSignature, String methodName) { + JavaMethod m = null; + for (JavaMethod method : javaClass.getMethods()) { + if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { + m = method; + } + } + if (m != null) { + return m; + } + if (javaClass.getSuperClass() == null) { + return null; + } + return getMethod(javaClass.getSuperClass(), methodSignature, methodName); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/JSR.java b/src/main/java/haidnor/jvm/instruction/references/JSR.java new file mode 100644 index 0000000..eccb23c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/JSR.java @@ -0,0 +1,30 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * JSR(Jump to Subroutine)指令是一条在Java虚拟机中用于进行子程序调用的指令。它将当前指令的返回地址压入操作数栈,并跳转到指定的子程序代码执行。子程序执行完毕后,通过RET(Return)指令返回到主程序的下一条指令继续执行。 + *

+ * JSR指令的操作码为0xA8,属于控制指令家族(Control Instructions)。它的操作数是一个16位的无符号偏移量,用于表示跳转目标的字节码偏移量。 + *

+ * 使用JSR指令可以实现方法的调用和返回,但在实际的Java字节码中,更常见的是使用invokestatic、invokevirtual等指令来进行方法调用。 + *

+ * 需要注意的是,JSR指令只在早期版本的Java虚拟机规范中存在,在Java SE 6及以后的版本中已被废弃,并且不建议在新的Java代码中使用。 + */ +public class JSR extends Instruction { + + public JSR(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("JSR"); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + throw new UnsupportedOperationException("JSR"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/JSR_W.java b/src/main/java/haidnor/jvm/instruction/references/JSR_W.java new file mode 100644 index 0000000..09513e8 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/JSR_W.java @@ -0,0 +1,26 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * 在早期版本的Java虚拟机规范中,存在JSR和JSR_W两个指令。其中,JSR指令用于进行子程序调用,而JSR_W指令用于进行宽跳转的子程序调用。宽跳转指令可以用于在字节码中的跳转偏移量超过16位时进行有效的跳转。 + *

+ * 然而,从Java SE 6及以后的版本开始,Java虚拟机规范已废弃了JSR_W指令,并且不建议在新的Java代码中使用。而是通过其他方式来实现跳转,例如使用ldc_w、ldc2_w和goto_w等指令结合进行宽跳转。 + */ +public class JSR_W extends Instruction { + + public JSR_W(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("JSR_W"); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + throw new UnsupportedOperationException("JSR"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/MONITORENTER.java b/src/main/java/haidnor/jvm/instruction/references/MONITORENTER.java new file mode 100644 index 0000000..58b9655 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/MONITORENTER.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class MONITORENTER extends Instruction { + + public MONITORENTER(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("MONITORENTER"); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + throw new UnsupportedOperationException("MONITORENTER"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/MONITOREXIT.java b/src/main/java/haidnor/jvm/instruction/references/MONITOREXIT.java new file mode 100644 index 0000000..9be38f1 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/MONITOREXIT.java @@ -0,0 +1,21 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class MONITOREXIT extends Instruction { + + public MONITOREXIT(CodeStream codeStream) { + super(codeStream); + throw new UnsupportedOperationException("MONITOREXIT"); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + throw new UnsupportedOperationException("MONITOREXIT"); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/NEW.java b/src/main/java/haidnor/jvm/instruction/references/NEW.java new file mode 100644 index 0000000..8770bfb --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/NEW.java @@ -0,0 +1,44 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.Const; +import haidnor.jvm.bcel.classfile.ConstantPool; +import haidnor.jvm.bcel.classfile.JavaClass; +import haidnor.jvm.bcel.classfile.Utility; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class NEW extends Instruction { + + private final int constantClassIndex; + + public NEW(CodeStream codeStream) { + super(codeStream); + this.constantClassIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + String className = constantPool.constantClass_ClassName(constantClassIndex); + + if (className.startsWith("java/")) { + frame.push(new StackValue(Const.T_OBJECT, null)); + return; + } + + JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className)); + if (javaClass == null) { + // 如果在元空间中找不到已加载的类,则开始进行类加载流程 + javaClass = frame.getJavaClass().getJVMClassLoader().loadWithClassPath(className); + } + Instance instance = javaClass.newInstance(); + frame.push(new StackValue(Const.T_OBJECT, instance)); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/NEWARRAY.java b/src/main/java/haidnor/jvm/instruction/references/NEWARRAY.java new file mode 100644 index 0000000..cce3c6e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/NEWARRAY.java @@ -0,0 +1,53 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; +import haidnor.jvm.bcel.Const; + +public class NEWARRAY extends Instruction { + + private final int type; + + public NEWARRAY(CodeStream codeStream) { + super(codeStream); + this.type = codeStream.readUnsignedByte(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + int size = frame.popInt(); + switch (type) { + case Const.T_BOOLEAN -> { + frame.pushRef(BasicTypeArray.boolArray(size)); + } + case Const.T_CHAR -> { + frame.pushRef(BasicTypeArray.charArray(size)); + } + case Const.T_FLOAT -> { + frame.pushRef(BasicTypeArray.floatArray(size)); + } + case Const.T_DOUBLE -> { + frame.pushRef(BasicTypeArray.doubleArray(size)); + } + case Const.T_BYTE -> { + frame.pushRef(BasicTypeArray.byteArray(size)); + } + case Const.T_SHORT -> { + frame.pushRef(BasicTypeArray.shortArray(size)); + } + case Const.T_INT -> { + frame.pushRef(BasicTypeArray.intArray(size)); + } + case Const.T_LONG -> { + frame.pushRef(BasicTypeArray.longArray(size)); + } + default -> throw new IllegalArgumentException(); + } + + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/PUTFIELD.java b/src/main/java/haidnor/jvm/instruction/references/PUTFIELD.java new file mode 100644 index 0000000..4057a96 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/PUTFIELD.java @@ -0,0 +1,36 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.classfile.ConstantPool; +import haidnor.jvm.bcel.classfile.JavaField; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class PUTFIELD extends Instruction { + + private final int constantFieldrefIndex; + + public PUTFIELD(CodeStream codeStream) { + super(codeStream); + this.constantFieldrefIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + + String filedName = constantPool.getFieldName(constantFieldrefIndex); + String fieldSignature = constantPool.getFieldSignature(constantFieldrefIndex); + + StackValue stackValue = frame.pop(); + + Instance instance = frame.popRef(); + JavaField field = instance.getField(filedName, fieldSignature); + field.setValue(stackValue); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java b/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java new file mode 100644 index 0000000..17b8357 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java @@ -0,0 +1,38 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.bcel.classfile.*; +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Metaspace; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * @author wang xiang + */ +public class PUTSTATIC extends Instruction { + + private final int constantFieldrefIndex; + + public PUTSTATIC(CodeStream codeStream) { + super(codeStream); + this.constantFieldrefIndex = codeStream.readUnsignedShort(this); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + ConstantPool constantPool = frame.getJavaMethod().getConstantPool(); + ConstantFieldref constFieldref = constantPool.getConstant(constantFieldrefIndex); + // 动态链接. 找到字段所属的 Java 类 + String className = constantPool.constantFieldref_ClassName(constFieldref); + // 动态链接. 找到字段的名字 + String fieldName = constantPool.getFieldName(constFieldref); + // 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数. + + JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className)); + JavaField staticField = javaClass.getStaticField(fieldName); + staticField.setValue(frame.pop()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP.java b/src/main/java/haidnor/jvm/instruction/stack/DUP.java new file mode 100644 index 0000000..e29a03b --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP.java @@ -0,0 +1,27 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class DUP extends Instruction { + + public DUP(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue = frame.pop(); + + // 判空是为了兼容创建 Java 对象, 创建rt.jar java对象时,执行 NEW 指令会在栈帧中存放一个 NULL + if (stackValue.getValue() != null) { + frame.push(stackValue); + frame.push(stackValue); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP2.java b/src/main/java/haidnor/jvm/instruction/stack/DUP2.java new file mode 100644 index 0000000..ea7e3dd --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP2.java @@ -0,0 +1,41 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * DUP2指令是一条Java虚拟机指令,用于复制栈顶两个元素,并将复制的值插入到栈顶之后。 + *

+ * DUP2指令有以下几种形式: + *

+ * 栈顶元素为A的情况: + *

+ * 执行DUP2指令后,栈的状态变为:A(副本)、A。 + * 栈顶元素为A和B的情况: + *

+ * 执行DUP2指令后,栈的状态变为:A(副本)、B、A、B。 + * 需要注意的是,在执行DUP2指令时,操作数栈必须至少有一个或两个元素,具体取决于栈顶元素的数量。如果栈顶元素只有一个,则只会复制该元素一次;如果栈顶元素有两个,则会分别复制两个元素。 + *

+ * 在Java虚拟机规范中,DUP2指令的操作码为0x5C,也属于堆栈管理指令家族(Stack Management Instructions)。 + */ +public class DUP2 extends Instruction { + + public DUP2(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + StackValue stackValue2 = frame.pop(); + frame.push(stackValue2); + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java new file mode 100644 index 0000000..32e8910 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java @@ -0,0 +1,36 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; +import haidnor.jvm.bcel.Const; + +public class DUP2_X1 extends Instruction { + + public DUP2_X1(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + StackValue stackValue2 = frame.pop(); + + if (stackValue1.getValueType() == Const.T_DOUBLE || stackValue1.getValueType() == Const.T_LONG) { + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue1); + } else { + StackValue stackValue3 = frame.pop(); + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue1); + frame.push(stackValue2); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java new file mode 100644 index 0000000..671ee27 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java @@ -0,0 +1,70 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; +import haidnor.jvm.bcel.Const; + +/** + * @author wang xiang + */ +public class DUP2_X2 extends Instruction { + + public DUP2_X2(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + // v1(64) + if (stackValue1.getValueType() == Const.T_DOUBLE || stackValue1.getValueType() == Const.T_LONG) { + StackValue stackValue2 = frame.pop(); + + // v1(64) v2(64) + if (stackValue2.getValueType() == Const.T_DOUBLE || stackValue2.getValueType() == Const.T_LONG) { + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue1); + } + // v1(64) v2(32) + else { + StackValue stackValue3 = frame.pop(); + + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue1); + } + } + // v1(32) + else { + StackValue stackValue2 = frame.pop(); + StackValue stackValue3 = frame.pop(); + + // v1(32) v2(32) v3(64) + if (stackValue3.getValueType() == Const.T_DOUBLE || stackValue3.getValueType() == Const.T_LONG) { + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue1); + frame.push(stackValue2); + } + // v1(32) v2(32) v3(32) v4(32) + else { + StackValue stackValue4 = frame.pop(); + + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue4); + frame.push(stackValue1); + frame.push(stackValue2); + } + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP_X1.java b/src/main/java/haidnor/jvm/instruction/stack/DUP_X1.java new file mode 100644 index 0000000..6829c32 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP_X1.java @@ -0,0 +1,36 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * DUP_X1指令是一条Java虚拟机指令,用于复制栈顶元素并插入到栈顶下面的第二个元素位置。 + *

+ * 具体而言,DUP_X1指令的作用是将栈顶元素复制一份,并将复制出的值插入到栈顶下面的第二个元素位置。这种操作会在栈上产生一个额外的副本,栈的深度会增加1。 + *

+ * 例如,如果栈顶是A,下面的两个元素是B和C,执行DUP_X1指令后,栈的状态将变为:A(副本)、B、C、A。 + *

+ * 在Java虚拟机规范中,DUP_X1指令的操作码为0x5A,属于堆栈管理指令家族(Stack Management Instructions)。 + *

+ * 需要注意的是,执行DUP_X1指令时,操作数栈必须至少有两个元素,否则指令无法正常执行。 + */ +public class DUP_X1 extends Instruction { + + public DUP_X1(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + StackValue stackValue2 = frame.pop(); + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP_X2.java b/src/main/java/haidnor/jvm/instruction/stack/DUP_X2.java new file mode 100644 index 0000000..e8430a3 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP_X2.java @@ -0,0 +1,47 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +/** + * DUP_X2指令是一条Java虚拟机指令,用于复制栈顶元素并插入到栈顶下面的第三个元素位置。 + *

+ * 具体而言,DUP_X2指令的作用是将栈顶元素复制一份,并将复制出的值插入到栈顶下面的第三个元素位置。这种操作会在栈上产生一个额外的副本,栈的深度会增加1。 + *

+ * 根据栈顶元素以及其后面的元素数量,DUP_X2指令有三种不同的形式: + *

+ * 栈顶元素为A,下面两个元素为B和C的情况: + *

+ * 执行DUP_X2指令后,栈的状态变为:A(副本)、B、C、A。 + * 栈顶元素为A,下面三个元素为B、C和D的情况: + *

+ * 执行DUP_X2指令后,栈的状态变为:A(副本)、B、C、D、A。 + * 栈顶元素为A,下面一个元素为B的情况: + *

+ * 执行DUP_X2指令后,栈的状态变为:A(副本)、B、A。 + * 在Java虚拟机规范中,DUP_X2指令的操作码为0x5C,也属于堆栈管理指令家族(Stack Management Instructions)。 + *

+ * 需要注意的是,执行DUP_X2指令时,操作数栈必须至少有两个或三个元素,具体取决于栈顶元素和其后面的元素的数量,否则指令无法正常执行。 + */ +public class DUP_X2 extends Instruction { + + public DUP_X2(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + StackValue stackValue2 = frame.pop(); + StackValue stackValue3 = frame.pop(); + frame.push(stackValue1); + frame.push(stackValue3); + frame.push(stackValue2); + frame.push(stackValue1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/POP.java b/src/main/java/haidnor/jvm/instruction/stack/POP.java new file mode 100644 index 0000000..3543f15 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/POP.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class POP extends Instruction { + + public POP(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + frame.pop(); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/POP2.java b/src/main/java/haidnor/jvm/instruction/stack/POP2.java new file mode 100644 index 0000000..289ae75 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/POP2.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class POP2 extends Instruction { + + public POP2(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + frame.pop(); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/SWAP.java b/src/main/java/haidnor/jvm/instruction/stack/SWAP.java new file mode 100644 index 0000000..ccf515e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/SWAP.java @@ -0,0 +1,24 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; + +public class SWAP extends Instruction { + + public SWAP(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + Instance v2 = frame.popRef(); + Instance v1 = frame.popRef(); + frame.pushRef(v2); + frame.pushRef(v1); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/AASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/AASTORE.java new file mode 100644 index 0000000..1a60aff --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/AASTORE.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.Instance; +import haidnor.jvm.rtda.InstanceArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class AASTORE extends Instruction { + + public AASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + Instance val = frame.popRef(); + int index = frame.popInt(); + InstanceArray array = (InstanceArray) frame.popRef(); + array.items[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java new file mode 100644 index 0000000..96a1b90 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ASTORE extends Instruction { + + private final int index; + + public ASTORE(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetRef(index, value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ASTORE_0.java b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_0.java new file mode 100644 index 0000000..930ba45 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_0.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ASTORE_0 extends Instruction { + + public ASTORE_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetRef(0, value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ASTORE_1.java b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_1.java new file mode 100644 index 0000000..14faefe --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_1.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ASTORE_1 extends Instruction { + + public ASTORE_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetRef(1, value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ASTORE_2.java b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_2.java new file mode 100644 index 0000000..c04efc9 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_2.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ASTORE_2 extends Instruction { + + public ASTORE_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetRef(2, value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ASTORE_3.java b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_3.java new file mode 100644 index 0000000..966d894 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_3.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ASTORE_3 extends Instruction { + + public ASTORE_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetRef(3, value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/BASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/BASTORE.java new file mode 100644 index 0000000..5bf333d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/BASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class BASTORE extends Instruction { + + public BASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int val = frame.popInt(); + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.ints[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/CASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/CASTORE.java new file mode 100644 index 0000000..c59dcdc --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/CASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class CASTORE extends Instruction { + + public CASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int val = frame.popInt(); + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.ints[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/DASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/DASTORE.java new file mode 100644 index 0000000..a4359b0 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/DASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class DASTORE extends Instruction { + + public DASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + double val = frame.popDouble(); + int index = frame.popInt(); + final BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.doubles[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/DSTORE.java b/src/main/java/haidnor/jvm/instruction/stores/DSTORE.java new file mode 100644 index 0000000..a6f18d9 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/DSTORE.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class DSTORE extends Instruction { + + private final int index; + + public DSTORE(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetDouble(index, (double) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/DSTORE_0.java b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_0.java new file mode 100644 index 0000000..e3e188b --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_0.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class DSTORE_0 extends Instruction { + + public DSTORE_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetDouble(0, (double) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/DSTORE_1.java b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_1.java new file mode 100644 index 0000000..9e9aad3 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_1.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class DSTORE_1 extends Instruction { + + public DSTORE_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetDouble(1, (double) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/DSTORE_2.java b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_2.java new file mode 100644 index 0000000..943ce56 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_2.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class DSTORE_2 extends Instruction { + + public DSTORE_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetDouble(2, (double) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/DSTORE_3.java b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_3.java new file mode 100644 index 0000000..874ecff --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/DSTORE_3.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class DSTORE_3 extends Instruction { + + public DSTORE_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetDouble(3, (double) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/FASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/FASTORE.java new file mode 100644 index 0000000..52ee484 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/FASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class FASTORE extends Instruction { + + public FASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + float val = frame.popFloat(); + int index = frame.popInt(); + final BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.floats[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/FSTORE.java b/src/main/java/haidnor/jvm/instruction/stores/FSTORE.java new file mode 100644 index 0000000..0b21d8b --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/FSTORE.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class FSTORE extends Instruction { + + private final int index; + + public FSTORE(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetFloat(index, (float) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/FSTORE_0.java b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_0.java new file mode 100644 index 0000000..9f3d662 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_0.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class FSTORE_0 extends Instruction { + + public FSTORE_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetFloat(0, (float) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/FSTORE_1.java b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_1.java new file mode 100644 index 0000000..39a02d4 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_1.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class FSTORE_1 extends Instruction { + + public FSTORE_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetFloat(1, (float) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/FSTORE_2.java b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_2.java new file mode 100644 index 0000000..93c878d --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_2.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class FSTORE_2 extends Instruction { + + public FSTORE_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetFloat(2, (float) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/FSTORE_3.java b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_3.java new file mode 100644 index 0000000..2fbc978 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/FSTORE_3.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class FSTORE_3 extends Instruction { + + public FSTORE_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetFloat(3, (float) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/IASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/IASTORE.java new file mode 100644 index 0000000..ce632e4 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/IASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class IASTORE extends Instruction { + + public IASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int val = frame.popInt(); + int index = frame.popInt(); + final BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.ints[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ISTORE.java b/src/main/java/haidnor/jvm/instruction/stores/ISTORE.java new file mode 100644 index 0000000..596adcc --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ISTORE.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ISTORE extends Instruction { + + private final int index; + + public ISTORE(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetInt(index, (int) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ISTORE_0.java b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_0.java new file mode 100644 index 0000000..34b1c45 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_0.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ISTORE_0 extends Instruction { + + public ISTORE_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetInt(0, (int) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ISTORE_1.java b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_1.java new file mode 100644 index 0000000..d48c064 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_1.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ISTORE_1 extends Instruction { + + public ISTORE_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetInt(1, (int) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ISTORE_2.java b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_2.java new file mode 100644 index 0000000..166bc3a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_2.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ISTORE_2 extends Instruction { + + public ISTORE_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetInt(2, (int) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ISTORE_3.java b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_3.java new file mode 100644 index 0000000..7e9fe6e --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/ISTORE_3.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class ISTORE_3 extends Instruction { + + public ISTORE_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetInt(3, (int) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/LASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/LASTORE.java new file mode 100644 index 0000000..f8b8a7c --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/LASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class LASTORE extends Instruction { + + public LASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + long val = frame.popLong(); + int index = frame.popInt(); + final BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.longs[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/LSTORE.java b/src/main/java/haidnor/jvm/instruction/stores/LSTORE.java new file mode 100644 index 0000000..764dbfd --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/LSTORE.java @@ -0,0 +1,23 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class LSTORE extends Instruction { + + private final int index; + + public LSTORE(CodeStream codeStream) { + super(codeStream); + this.index = codeStream.readUnsignedByte(this); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetLong(index, (long) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/LSTORE_0.java b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_0.java new file mode 100644 index 0000000..2c5711a --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_0.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class LSTORE_0 extends Instruction { + + public LSTORE_0(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetLong(0, (long) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/LSTORE_1.java b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_1.java new file mode 100644 index 0000000..3b3d390 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_1.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class LSTORE_1 extends Instruction { + + public LSTORE_1(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetLong(1, (long) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/LSTORE_2.java b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_2.java new file mode 100644 index 0000000..e993b72 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_2.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class LSTORE_2 extends Instruction { + + public LSTORE_2(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetLong(2, (long) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/LSTORE_3.java b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_3.java new file mode 100644 index 0000000..eb4cb25 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/LSTORE_3.java @@ -0,0 +1,20 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; + +public class LSTORE_3 extends Instruction { + + public LSTORE_3(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + StackValue value = frame.pop(); + frame.slotSetLong(3, (long) value.getValue()); + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/SASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/SASTORE.java new file mode 100644 index 0000000..4d4ebf6 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stores/SASTORE.java @@ -0,0 +1,22 @@ +package haidnor.jvm.instruction.stores; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.BasicTypeArray; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.util.CodeStream; + +public class SASTORE extends Instruction { + + public SASTORE(CodeStream codeStream) { + super(codeStream); + } + + @Override + public void execute(Frame frame) { + int val = frame.popInt(); + int index = frame.popInt(); + BasicTypeArray array = (BasicTypeArray) frame.popRef(); + array.ints[index] = val; + } + +} diff --git a/src/main/java/haidnor/jvm/rtda/Instance.java b/src/main/java/haidnor/jvm/rtda/Instance.java index 588e6fe..44979ad 100644 --- a/src/main/java/haidnor/jvm/rtda/Instance.java +++ b/src/main/java/haidnor/jvm/rtda/Instance.java @@ -14,12 +14,18 @@ public class Instance { @Getter private final JavaClass javaClass; - private final List javaFieldList = new ArrayList<>(); + private final List javaFieldList; private Instance superInstance; public Instance(JavaClass javaClass) { this.javaClass = javaClass; + this.javaFieldList = new ArrayList<>(); + } + + public Instance(List javaFieldList, JavaClass javaClass) { + this.javaFieldList = javaFieldList; + this.javaClass = javaClass; } public void setSuperInstance(Instance superInstance) { diff --git a/src/main/java/haidnor/jvm/runtime/Frame.java b/src/main/java/haidnor/jvm/runtime/Frame.java index 890f257..7276226 100644 --- a/src/main/java/haidnor/jvm/runtime/Frame.java +++ b/src/main/java/haidnor/jvm/runtime/Frame.java @@ -64,9 +64,6 @@ public class Frame { return this.code.getCode().length; } - public JavaMethod getMetaMethod() { - return javaMethod; - } /* 操作数栈操作 --------------------------------------------------------------------------------------------------- */ diff --git a/src/test/java/haidnor/jvm/Student.java b/src/test/java/haidnor/jvm/Student.java deleted file mode 100644 index 61aa27b..0000000 --- a/src/test/java/haidnor/jvm/Student.java +++ /dev/null @@ -1,6 +0,0 @@ -package haidnor.jvm; - -public class Student extends SuperStudent{ - private static String name; - -} diff --git a/src/test/java/haidnor/jvm/SuperStudent.java b/src/test/java/haidnor/jvm/SuperStudent.java deleted file mode 100644 index 9ebb66e..0000000 --- a/src/test/java/haidnor/jvm/SuperStudent.java +++ /dev/null @@ -1,6 +0,0 @@ -package haidnor.jvm; - -public class SuperStudent { - private static String name; - -} diff --git a/src/test/java/haidnor/jvm/test/BCELTest.java b/src/test/java/haidnor/jvm/test/BCELTest.java deleted file mode 100644 index f775631..0000000 --- a/src/test/java/haidnor/jvm/test/BCELTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package haidnor.jvm.test; - -import haidnor.jvm.bcel.classfile.JavaClass; -import haidnor.jvm.classloader.JVMClassLoader; - -import java.io.IOException; - -public class BCELTest { - public static void main(String[] args) throws IOException { - JVMClassLoader classLoader = new JVMClassLoader("JVMClassLoader"); - JavaClass javaClass = classLoader.loadWithAbsolutePath("D:\\project_haidnor\\haidnorJVM\\target\\test-classes\\haidnor\\jvm\\Student.class"); - - System.out.println(javaClass.getStaticJavaFieldMap()); - } -} diff --git a/src/test/java/haidnor/jvm/test/TestJVM.java b/src/test/java/haidnor/jvm/test/TestJVM.java new file mode 100644 index 0000000..d14a5dc --- /dev/null +++ b/src/test/java/haidnor/jvm/test/TestJVM.java @@ -0,0 +1,173 @@ +package haidnor.jvm.test; + +import haidnor.jvm.HaidnorJVM; +import haidnor.jvm.test.demo.*; +import haidnor.jvm.test.instruction.Array; +import haidnor.jvm.test.instruction.DO_WHILE; +import haidnor.jvm.test.instruction.math.ISUB; +import haidnor.jvm.test.instruction.math.LSUB; +import haidnor.jvm.test.instruction.references.NEW; +import org.junit.Test; + +public class TestJVM { + + + /** + * hello,world + */ + @Test + public void test_1() throws Exception { + HaidnorJVM.testRun(demo_helloWorld.class); + } + + @Test + public void test_2() throws Exception { + HaidnorJVM.testRun(Demo2.class); + } + + @Test + public void test_3() throws Exception { + HaidnorJVM.testRun(Demo3.class); + } + + @Test + public void test_4() throws Exception { + HaidnorJVM.testRun(Demo4.class); + } + + @Test + public void test_5() throws Exception { + HaidnorJVM.testRun(Demo5.class); + } + + @Test + public void test_6() throws Exception { + HaidnorJVM.testRun(Demo6.class); + } + + @Test + public void test_7() throws Exception { + HaidnorJVM.testRun(Demo7.class); + } + + @Test + public void test_8() throws Exception { + HaidnorJVM.testRun(Demo8.class); + } + + @Test + public void demo_while() throws Exception { + HaidnorJVM.testRun(demo_while.class); + } + + @Test + public void demo_doWhile() throws Exception { + HaidnorJVM.testRun(demo_doWhile.class); + } + + @Test + public void demo_for() throws Exception { + HaidnorJVM.testRun(demo_for.class); + } + + @Test + public void demo_foreach() throws Exception { + HaidnorJVM.testRun(demo_foreach_1.class); + } + + /** + * --add-opens java.base/java.util=ALL-UNNAMED + */ + @Test + public void demo_foreach_2() throws Exception { + // runMainClass(demo_foreach_2.class); + } + + /** + * --add-opens java.base/java.util=ALL-UNNAMED + */ + @Test + public void demo_foreach_3() throws Exception { + // TODO wangxiang fix bug + // runMainClass(demo_foreach_3.class); + } + + @Test(expected = ArithmeticException.class) + public void demo_exception_1() throws Exception { + HaidnorJVM.testRun(demo_exception_1.class); + } + + @Test + public void demo_exception_2() throws Exception { + HaidnorJVM.testRun(demo_exception_2.class); + } + + @Test + public void demo_exception_3() throws Exception { + HaidnorJVM.testRun(demo_exception_3.class); + } + + @Test(expected = ArithmeticException.class) + public void demo_exception_4() throws Exception { + HaidnorJVM.testRun(demo_exception_4.class); + } + + @Test + public void demo_finally_1() throws Exception { + HaidnorJVM.testRun(demo_finally_1.class); + } + + @Test(expected = ArithmeticException.class) + public void demo_finally_2() throws Exception { + HaidnorJVM.testRun(demo_finally_2.class); + } + + @Test(expected = ArithmeticException.class) + public void demo_finally_3() throws Exception { + HaidnorJVM.testRun(demo_finally_3.class); + } + + + @Test + public void demo_enum_1() throws Exception { + // TODO support enum + // runMainClass(demo_enum_1.class); + } + + @Test + public void test_NEW() throws Exception { + HaidnorJVM.testRun(NEW.class); + } + + @Test + public void test_ISUB() throws Exception { + HaidnorJVM.testRun(ISUB.class); + } + + @Test + public void test_LSUB() throws Exception { + HaidnorJVM.testRun(LSUB.class); + } + + @Test + public void test_DOWHILE() throws Exception { + HaidnorJVM.testRun(DO_WHILE.class); + } + + @Test + public void test_Array() throws Exception { + HaidnorJVM.testRun(Array.class); + } + + @Test + public void test_() throws Exception { + long longNum = 922337203685477580L; // Long Max + + int[] arr = new int[2]; + arr[0] = (int) (longNum >> 32); // 获取高位部分 + arr[1] = (int) (longNum & 0xFFFFFFFFL); // 获取低位部分 + + long result = ((long) arr[0] << 32) | ((long) arr[1] & 0xFFFFFFFFL); + System.out.println(result); + } +} diff --git a/src/test/java/haidnor/jvm/test/clazz/Func.java b/src/test/java/haidnor/jvm/test/clazz/Func.java new file mode 100644 index 0000000..96212c9 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/Func.java @@ -0,0 +1,7 @@ +package haidnor.jvm.test.clazz; + +@FunctionalInterface +public interface Func { + + boolean func(String str); +} diff --git a/src/test/java/haidnor/jvm/test/clazz/HelloWorld.java b/src/test/java/haidnor/jvm/test/clazz/HelloWorld.java new file mode 100644 index 0000000..6b445ec --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/HelloWorld.java @@ -0,0 +1,8 @@ +package haidnor.jvm.test.clazz; + +public class HelloWorld { + public static void main(String[] args) { + int a = 1; + a++; + } +} diff --git a/src/test/java/haidnor/jvm/test/clazz/Human.java b/src/test/java/haidnor/jvm/test/clazz/Human.java new file mode 100644 index 0000000..0bc3a54 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/Human.java @@ -0,0 +1,16 @@ +package haidnor.jvm.test.clazz; + +public abstract class Human implements Organism { + + public static final String HUMAN_NAME = "123"; + + static { + System.out.println("Human 类被加载了"); + } + + public void eat() { + Object o = new Object(); + System.out.println("人类吃饭"); + } + +} diff --git a/src/test/java/haidnor/jvm/test/clazz/Organism.java b/src/test/java/haidnor/jvm/test/clazz/Organism.java new file mode 100644 index 0000000..3e6f9b1 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/Organism.java @@ -0,0 +1,8 @@ +package haidnor.jvm.test.clazz; + +/** + * 生物 + */ +public interface Organism extends Organism0 { + +} diff --git a/src/test/java/haidnor/jvm/test/clazz/Organism0.java b/src/test/java/haidnor/jvm/test/clazz/Organism0.java new file mode 100644 index 0000000..fd9a393 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/Organism0.java @@ -0,0 +1,12 @@ +package haidnor.jvm.test.clazz; + +/** + * 生物 + */ +public interface Organism0 { + + default void die() { + System.out.println("Organism die 0"); + } + +} diff --git a/src/test/java/haidnor/jvm/test/clazz/Student.java b/src/test/java/haidnor/jvm/test/clazz/Student.java new file mode 100644 index 0000000..f393a22 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/Student.java @@ -0,0 +1,19 @@ +package haidnor.jvm.test.clazz; + +public class Student extends Human implements Organism { + + public void method1() { + System.out.println("method1"); + method2(); + } + + public void method2() { + System.out.println("method2"); + method3(); + } + + public void method3() { + System.out.println("method3"); + } + +} diff --git a/src/test/java/haidnor/jvm/test/clazz/StudentEnum.java b/src/test/java/haidnor/jvm/test/clazz/StudentEnum.java new file mode 100644 index 0000000..8996e49 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/clazz/StudentEnum.java @@ -0,0 +1,23 @@ +package haidnor.jvm.test.clazz; + +public enum StudentEnum { + + ZHANG_SAN(1,"张三"); + + private int age; + private String name; + + StudentEnum(int age, String name) { + this.age = age; + this.name = name; + } + + public int getAge() { + return age; + } + + public String getName() { + return name; + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/Demo2.java b/src/test/java/haidnor/jvm/test/demo/Demo2.java new file mode 100644 index 0000000..77ae088 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo2.java @@ -0,0 +1,12 @@ +package haidnor.jvm.test.demo; + +public class Demo2 { + + public static void main(String[] args) { + long longVal = 1L; + float floatVal = 1f; + double doubleVal = 1D; + int intVal = 1; + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/Demo3.java b/src/test/java/haidnor/jvm/test/demo/Demo3.java new file mode 100644 index 0000000..97b40ca --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo3.java @@ -0,0 +1,22 @@ +package haidnor.jvm.test.demo; + +import haidnor.jvm.test.clazz.Student; + +import java.util.HashMap; + +public class Demo3 { + + public static void main(String[] args) { + Student sut1 = new Student(); + Student sut2 = new Student(); + + HashMap hashMap = new HashMap<>(); + hashMap.put(sut1, "张三123"); + hashMap.put(sut2, "张三"); + + System.out.println(hashMap.get(sut1)); // 1 + System.out.println(hashMap.get(sut2)); // 2 + } + +} + diff --git a/src/test/java/haidnor/jvm/test/demo/Demo4.java b/src/test/java/haidnor/jvm/test/demo/Demo4.java new file mode 100644 index 0000000..23532f4 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo4.java @@ -0,0 +1,12 @@ +package haidnor.jvm.test.demo; + +import haidnor.jvm.test.clazz.Student; + +public class Demo4 { + + public static void main(String[] args) { + Student student = new Student(); + student.method1(); + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/Demo5.java b/src/test/java/haidnor/jvm/test/demo/Demo5.java new file mode 100644 index 0000000..2b42a16 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo5.java @@ -0,0 +1,27 @@ +package haidnor.jvm.test.demo; + +public class Demo5 { + + static { + System.out.println("hello,world"); + } + + public static void main(String[] args) { + String str = method1("hello world"); + method1(str); + } + + public static String method1(String s) { + return method2(s); + } + + public static String method2(String s) { + return method3(s); + } + + public static String method3(String s) { + System.out.println(s); + return "你好 世界"; + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/Demo6.java b/src/test/java/haidnor/jvm/test/demo/Demo6.java new file mode 100644 index 0000000..751d337 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo6.java @@ -0,0 +1,16 @@ +package haidnor.jvm.test.demo; + + +import haidnor.jvm.test.clazz.Human; +import haidnor.jvm.test.clazz.Student; + +public class Demo6 { + + public static void main(String[] args) { + Student student = new Student(); + if (student instanceof Human) { + System.out.println("true"); + } + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/Demo7.java b/src/test/java/haidnor/jvm/test/demo/Demo7.java new file mode 100644 index 0000000..3c12882 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo7.java @@ -0,0 +1,20 @@ +package haidnor.jvm.test.demo; + + +public class Demo7 { + + public static void main(String[] args) { + try { + String name = fun(); + System.out.println(name); + } catch (Exception exception) { + System.out.println("计算错误"); + } + } + + public static String fun() { + System.out.println(1 / 0); + return "zhangsan"; + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/Demo8.java b/src/test/java/haidnor/jvm/test/demo/Demo8.java new file mode 100644 index 0000000..3b13d12 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo8.java @@ -0,0 +1,17 @@ +package haidnor.jvm.test.demo; + + +import haidnor.jvm.test.clazz.Human; +import haidnor.jvm.test.clazz.Organism0; +import haidnor.jvm.test.clazz.Student; + +public class Demo8 { + + public static void main(String[] args) { + Human organism1 = new Student(); + Organism0 organism = new Student(); + organism.die(); + } + + +} diff --git a/src/test/java/haidnor/jvm/test/demo/demo_add.java b/src/test/java/haidnor/jvm/test/demo/demo_add.java new file mode 100644 index 0000000..b25a1ed --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_add.java @@ -0,0 +1,17 @@ +package haidnor.jvm.test.demo; + +public class demo_add { + public static void main(String[] args) { + hello(); + } + + public static void hello() { + System.out.println("hello"); + hello1(); + } + + public static void hello1() { + System.out.println("hello"); + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/demo_doWhile.java b/src/test/java/haidnor/jvm/test/demo/demo_doWhile.java new file mode 100644 index 0000000..3794892 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_doWhile.java @@ -0,0 +1,27 @@ +package haidnor.jvm.test.demo; + +public class demo_doWhile { + public static void main(String[] args) { + int a = 0; + do { + a++; + } while (a < 2); + System.out.println(a); + } +} + +/* +main(String[] args): + 0 iconst_0 + 1 istore_1 + + 2 iinc 1 by 1 + 5 iload_1 + 6 iconst_2 + 7 if_icmplt 2 (-5) < while (a < 2); 符合条件则向前跳转 + + 10 getstatic #7 + 13 iload_1 + 14 invokevirtual #13 + 17 return + */ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_enum_1.java b/src/test/java/haidnor/jvm/test/demo/demo_enum_1.java new file mode 100644 index 0000000..a5472c5 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_enum_1.java @@ -0,0 +1,11 @@ +package haidnor.jvm.test.demo; + +import haidnor.jvm.test.clazz.StudentEnum; + +public class demo_enum_1 { + public static void main(String[] args) { + StudentEnum studentEnum = StudentEnum.ZHANG_SAN; + System.out.println(studentEnum.getAge()); + System.out.println(studentEnum.getName()); + } +} diff --git a/src/test/java/haidnor/jvm/test/demo/demo_exception_1.java b/src/test/java/haidnor/jvm/test/demo/demo_exception_1.java new file mode 100644 index 0000000..4fd0885 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_exception_1.java @@ -0,0 +1,37 @@ +package haidnor.jvm.test.demo; + +/** + * 调用方没有捕获调用方法的异常 + */ +public class demo_exception_1 { + + public static void main(String[] args) { + int a = 0; + fun(a); + } + + public static void fun(int a) { + if (a == 0) { + throw new ArithmeticException(); + } + } + +} +/* +main(String[] args) + 0 iconst_0 + 1 istore_1 + 2 iload_1 + 3 invokestatic #7 + 6 return + +fun(int a) + 0 iload_0 + 1 ifne 12 (+11) + 4 new #29 + 7 dup + 8 invokespecial #31 : ()V> + 11 athrow + 12 return + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_exception_2.java b/src/test/java/haidnor/jvm/test/demo/demo_exception_2.java new file mode 100644 index 0000000..d9dc426 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_exception_2.java @@ -0,0 +1,53 @@ +package haidnor.jvm.test.demo; + +/** + * 调用方捕获调用方法的异常 + */ +public class demo_exception_2 { + + public static void main(String[] args) { + int a = 0; + try { + fun(a); + } catch (Exception exception) { + System.out.println("catch Exception"); + } + } + + public static void fun(int a) { + if (a == 0) { + throw new ArithmeticException(); + } + } + +} +/* +main(String[] args) + 0 iconst_0 + 1 istore_1 + 2 iload_1 + 3 invokestatic #7 + 6 goto 18 (+12) + 9 astore_2 + 10 getstatic #15 + 13 ldc #21 + 15 invokevirtual #23 + 18 return + ++--------+-------+--------+--------+---------------------+ +| Nr. | 起始PC | 结束PC | 跳转PC | 捕获类型 | ++--------+-------+--------+--------+---------------------+ +| 0 | 2 | 6 | 9 | java/lang/Exception | ++--------+-------+--------+--------+---------------------+ + + +fun(int a) + 0 iload_0 + 1 ifne 12 (+11) + 4 new #29 + 7 dup + 8 invokespecial #31 : ()V> + 11 athrow + 12 return + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_exception_3.java b/src/test/java/haidnor/jvm/test/demo/demo_exception_3.java new file mode 100644 index 0000000..57f9893 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_exception_3.java @@ -0,0 +1,50 @@ +package haidnor.jvm.test.demo; + +/** + * 调用方捕获调用方法的异常的父类 + */ +public class demo_exception_3 { + + public static void main(String[] args) { + int a = 0; + try { + fun(a); + } catch (Exception exception) { + System.out.println("catch Exception"); + } + } + + public static void fun(int a) { + System.out.println(1 / a); + } + +} +/* +main(String[] args) + 0 iconst_0 + 1 istore_1 + 2 iload_1 + 3 invokestatic #7 + 6 goto 18 (+12) + 9 astore_2 + 10 getstatic #15 + 13 ldc #21 + 15 invokevirtual #23 + 18 return + ++--------+-------+--------+--------+---------------------+ +| Nr. | 起始PC | 结束PC | 跳转PC | 捕获类型 | ++--------+-------+--------+--------+---------------------+ +| 0 | 2 | 6 | 9 | java/lang/Exception | ++--------+-------+--------+--------+---------------------+ + + +fun(int a) + 0 getstatic #15 + 3 iconst_1 + 4 iload_0 + 5 idiv + 6 invokevirtual #29 + 9 return + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_exception_4.java b/src/test/java/haidnor/jvm/test/demo/demo_exception_4.java new file mode 100644 index 0000000..c22e908 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_exception_4.java @@ -0,0 +1,50 @@ +package haidnor.jvm.test.demo; + +/** + * 调用方没有捕获调用方法抛出的异常类型 + */ +public class demo_exception_4 { + + public static void main(String[] args) { + int a = 0; + try { + fun(a); + } catch (NullPointerException exception) { + System.out.println("catch Exception"); + } + } + + public static void fun(int a) { + System.out.println(1 / a); + } + +} +/* +main(String[] args) + 0 iconst_0 + 1 istore_1 + 2 iload_1 + 3 invokestatic #7 + 6 goto 18 (+12) + 9 astore_2 + 10 getstatic #15 + 13 ldc #21 + 15 invokevirtual #23 + 18 return + ++--------+-------+--------+--------+--------------------------------+ +| Nr. | 起始PC | 结束PC | 跳转PC | 捕获类型 | ++--------+-------+--------+--------+--------------------------------+ +| 0 | 2 | 6 | 9 | java/lang/NullPointerException | ++--------+-------+--------+--------+--------------------------------+ + + +fun(int a) + 0 getstatic #15 + 3 iconst_1 + 4 iload_0 + 5 idiv + 6 invokevirtual #29 + 9 return + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_finally_1.java b/src/test/java/haidnor/jvm/test/demo/demo_finally_1.java new file mode 100644 index 0000000..23398c3 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_finally_1.java @@ -0,0 +1,51 @@ +package haidnor.jvm.test.demo; + +public class demo_finally_1 { + + public static void main(String[] args) { + String name = fun(); + System.out.println(name); + } + + public static String fun() { + String str = "zhang san"; + try { + return str; + } finally { + str = "li si"; + } + } + +} +/* +main(String[] args): + 0 invokestatic #7 + 3 astore_1 + 4 getstatic #13 + 7 aload_1 + 8 invokevirtual #19 + 11 return + +fun(): + 0 ldc #25 + 2 astore_0 + 3 aload_0 + 4 astore_1 + 5 ldc #27

  • + 7 astore_0 + 8 aload_1 + 9 areturn + 10 astore_2 < 如果 3-5 指令出现了异常时才会跳转到 10. 如果出现了异常会把异常压入操作数栈,这里的 astore_2 就是把异常先存储起来。 + 11 ldc #27
  • + 13 astore_0 + 14 aload_2 < 执行完 finally 把 astore_2 的异常压入操作树栈 + 15 athrow < 把操作数栈上的异常抛出 + +Exception Table: ++--------+-------+--------+--------+---------+ +| Nr. | 起始PC | 结束PC | 跳转PC | 捕获类型 | ++--------+-------+--------+--------+---------+ +| 0 | 3 | 5 | 10 | any | ++--------+-------+--------+--------+---------+ + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_finally_2.java b/src/test/java/haidnor/jvm/test/demo/demo_finally_2.java new file mode 100644 index 0000000..4474c5e --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_finally_2.java @@ -0,0 +1,55 @@ +package haidnor.jvm.test.demo; + +/** + * try 异常后执行 finally + */ +public class demo_finally_2 { + + public static void main(String[] args) { + fun(); + } + + public static void fun() { + try { + System.out.println(1 / 0); + } finally { + System.out.println("此时应该执行 finally"); + } + } + +} +/* +main(String[] args): + 0 invokestatic #7 + 3 return + + +fun(): + 0 getstatic #12 + 3 iconst_1 + 4 iconst_0 + 5 idiv + 6 invokevirtual #18 + 9 getstatic #12 + 12 ldc #24 + 14 invokevirtual #26 + 17 getstatic #12 + 20 ldc #29 <此时不应该执行 finally> + 22 invokevirtual #26 + 25 goto 39 (+14) + 28 astore_0 + 29 getstatic #12 + 32 ldc #29 <此时不应该执行 finally> + 34 invokevirtual #26 + 37 aload_0 + 38 athrow + 39 return + +Exception Table: ++--------+-------+--------+--------+---------+ +| Nr. | 起始PC | 结束PC | 跳转PC | 捕获类型 | ++--------+-------+--------+--------+---------+ +| 0 | 9 | 17 | 28 | any | ++--------+-------+--------+--------+---------+ + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_finally_3.java b/src/test/java/haidnor/jvm/test/demo/demo_finally_3.java new file mode 100644 index 0000000..f854020 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_finally_3.java @@ -0,0 +1,55 @@ +package haidnor.jvm.test.demo; + +/** + * try 异常前不应该执行 finally + */ +public class demo_finally_3 { + + public static void main(String[] args) { + fun(); + } + + public static void fun() { + System.out.println(1 / 0); + try { + System.out.println("try"); + } finally { + System.out.println("finally"); + } + } + +} +/* +main(String[] args): + 0 invokestatic #7 + 3 return + +fun(): + 0 getstatic #12 + 3 iconst_1 + 4 iconst_0 + 5 idiv + 6 invokevirtual #18 + 9 getstatic #12 + 12 ldc #24 + 14 invokevirtual #26 + 17 getstatic #12 + 20 ldc #29 + 22 invokevirtual #26 + 25 goto 39 (+14) + 28 astore_0 + 29 getstatic #12 + 32 ldc #29 + 34 invokevirtual #26 + 37 aload_0 + 38 athrow + 39 return + +Exception Table: ++--------+-------+--------+--------+---------+ +| Nr. | 起始PC | 结束PC | 跳转PC | 捕获类型 | ++--------+-------+--------+--------+---------+ +| 0 | 9 | 17 | 28 | any | ++--------+-------+--------+--------+---------+ + +*/ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_for.java b/src/test/java/haidnor/jvm/test/demo/demo_for.java new file mode 100644 index 0000000..4f93b21 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_for.java @@ -0,0 +1,31 @@ +package haidnor.jvm.test.demo; + +public class demo_for { + public static void main(String[] args) { + int a = 0; + for (int i = 0; i < 3; i++) { + a++; + } + System.out.println(a); + } +} + +/* +main(String[] args): + 0 iconst_0 < int a = 0 + 1 istore_1 + 2 iconst_0 < int i =0 + 3 istore_2 + + 4 iload_2 + 5 iconst_3 < 比较值3 + 6 if_icmpge 18 (+12) < (i < 3) + 9 iinc 1 by 1 < a++ + 12 iinc 2 by 1 < i++ + 15 goto 4 (-11) < 向前跳转代码 + + 18 getstatic #7 + 21 iload_1 + 22 invokevirtual #13 + 25 return + */ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_foreach_1.java b/src/test/java/haidnor/jvm/test/demo/demo_foreach_1.java new file mode 100644 index 0000000..e92f727 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_foreach_1.java @@ -0,0 +1,62 @@ +package haidnor.jvm.test.demo; + +public class demo_foreach_1 { + public static void main(String[] args) { + int[] arr = new int[]{999, 333}; + for (int i : arr) { + System.out.println(i); + } + } +} + +/* +main(String[] args): + 0 iconst_2 < 操作数栈压入2,这个是 arr[] 的长度 + 1 newarray 10 (int) < 创建数组 + 3 dup + + 4 iconst_0 + 5 sipush 999 + 8 iastore < arr[0] = 999 + + 9 dup < 复制栈顶的 arr[], 压入操作数栈 + + 10 iconst_1 + 11 sipush 333 + 14 iastore < arr[1] = 333 + + 15 astore_1 + 16 aload_1 + 17 astore_2 + 18 aload_2 + 19 arraylength + 20 istore_3 + 21 iconst_0 + 22 istore 4 + + 24 iload 4 + 26 iload_3 + 27 if_icmpge 50 (+23) + 30 aload_2 + 31 iload 4 + 33 iaload + 34 istore 5 + 36 getstatic #7 + 39 iload 5 + 41 invokevirtual #13 + 44 iinc 4 by 1 + 47 goto 24 (-23) + + 50 return + ++--------+-------+--------+--------+-----------+-------------------------+ +| Nr. | 起始PC | 长度 | 序号 | 名字 | 描述符(存储类型) | ++--------+-------+--------+--------+-----------+-------------------------+ +| 0 | 0 | 51 | 0 | args | [Ljava/lang/String; | ++--------+-------+--------+--------+-----------+-------------------------+ +| 1 | 16 | 35 | 1 | arr | [I | ++--------+-------+--------+--------+-----------+-------------------------+ +| 2 | 36 | 8 | 5 | i | I | ++--------+-------+--------+--------+-----------+-------------------------+ + + */ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_foreach_2.java b/src/test/java/haidnor/jvm/test/demo/demo_foreach_2.java new file mode 100644 index 0000000..7c34984 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_foreach_2.java @@ -0,0 +1,25 @@ +package haidnor.jvm.test.demo; + +import java.util.ArrayList; +import java.util.List; + +/** + * 需要添加启动参数 + * --add-opens java.base/java.util=ALL-UNNAMED + */ +public class demo_foreach_2 { + + public static void main(String[] args) { + List list = new ArrayList<>(); + list.add(1); + list.add(2); + for (int i = 0; i < 1000; i++) { + list.add(i); + } + + for (Integer integer : list) { + System.out.println(integer); + } + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/demo_foreach_3.java b/src/test/java/haidnor/jvm/test/demo/demo_foreach_3.java new file mode 100644 index 0000000..95b5488 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_foreach_3.java @@ -0,0 +1,20 @@ +package haidnor.jvm.test.demo; + +import java.util.List; + +/** + * 需要添加启动参数 + * --add-opens java.base/java.util=ALL-UNNAMED + */ +public class demo_foreach_3 { + + public static void main(String[] args) { + List list = List.of(1, 2, 3, 4, 5); + list.add(6); + +// for (Integer integer : list) { +// System.out.println(integer); +// } + } + +} diff --git a/src/test/java/haidnor/jvm/test/demo/demo_helloWorld.java b/src/test/java/haidnor/jvm/test/demo/demo_helloWorld.java new file mode 100644 index 0000000..5d1b057 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_helloWorld.java @@ -0,0 +1,18 @@ +package haidnor.jvm.test.demo; + +public class demo_helloWorld { + + public static void main(String[] args) { + System.out.println("hello,world"); + } + +} +/* + +main(String[] args) + 0 getstatic #7 + 3 ldc #13 + 5 invokevirtual #15 + 8 return + + */ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo/demo_while.java b/src/test/java/haidnor/jvm/test/demo/demo_while.java new file mode 100644 index 0000000..bb08e63 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/demo_while.java @@ -0,0 +1,29 @@ +package haidnor.jvm.test.demo; + +public class demo_while { + public static void main(String[] args) { + int a = 0; + while (a < 2) { + a++; + } + System.out.println(a); + } +} + +/* +main(String[] args): + 0 iconst_0 + 1 istore_1 + 2 iload_1 + 3 iconst_2 + + 4 if_icmpge 13 (+9) < 符合条件就进入循环体 + 7 iinc 1 by 1 < a++ + 10 goto 2 (-8) < 向前跳转指令 + + 13 getstatic #7 + 16 iload_1 + 17 invokevirtual #13 + 20 return + + */ \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/demo1/Test1.java b/src/test/java/haidnor/jvm/test/demo1/Test1.java new file mode 100644 index 0000000..429c457 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo1/Test1.java @@ -0,0 +1,22 @@ +package haidnor.jvm.test.demo1; + +import haidnor.jvm.HaidnorJVM; + +public class Test1 { + public static void main(String[] args) { + HaidnorJVM.testRun(TestClass.class); + } + +} + +/** + * 0 getstatic #7 + * 3 ldc #13 + * 5 invokevirtual #15 + * 8 return + */ +class TestClass { + public static void main(String[] args) { + System.out.println("hello,world"); + } +} \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/instruction/Array.java b/src/test/java/haidnor/jvm/test/instruction/Array.java new file mode 100644 index 0000000..efece48 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/Array.java @@ -0,0 +1,10 @@ +package haidnor.jvm.test.instruction; + +import haidnor.jvm.test.instruction.loads.Student1; + +public class Array { + public static void main(String[] args) { + Student1[] strArr = new Student1[10]; + strArr[5] = new Student1(); + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/ClassA.java b/src/test/java/haidnor/jvm/test/instruction/ClassA.java new file mode 100644 index 0000000..17dcc7c --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/ClassA.java @@ -0,0 +1,12 @@ +package haidnor.jvm.test.instruction; + +public class ClassA { + public static class ClassB { + + public int a; + + public ClassB(int a) { + this.a = a; + } + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/DO_WHILE.java b/src/test/java/haidnor/jvm/test/instruction/DO_WHILE.java new file mode 100644 index 0000000..3427855 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/DO_WHILE.java @@ -0,0 +1,11 @@ +package haidnor.jvm.test.instruction; + +public class DO_WHILE { + public static void main(String[] args) { + int a = 3; + do { + System.out.println(a); + a--; + } while (a != 0); + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/GOTO.java b/src/test/java/haidnor/jvm/test/instruction/GOTO.java new file mode 100644 index 0000000..bbe4134 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/GOTO.java @@ -0,0 +1,13 @@ +package haidnor.jvm.test.instruction; + +public class GOTO { + + public static void main(String[] args) { + int a = 1; + while (a < 10) { + System.out.println(a); + a++; + } + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/InnerClass.java b/src/test/java/haidnor/jvm/test/instruction/InnerClass.java new file mode 100644 index 0000000..c407f98 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/InnerClass.java @@ -0,0 +1,9 @@ +package haidnor.jvm.test.instruction; + +public class InnerClass { + public static void main(String[] args) { + ClassA.ClassB classB = new ClassA.ClassB(999); + + System.out.println(classB.a); + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/loads/Person.java b/src/test/java/haidnor/jvm/test/instruction/loads/Person.java new file mode 100644 index 0000000..012d01b --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/loads/Person.java @@ -0,0 +1,4 @@ +package haidnor.jvm.test.instruction.loads; + +public abstract class Person { +} diff --git a/src/test/java/haidnor/jvm/test/instruction/loads/Student.java b/src/test/java/haidnor/jvm/test/instruction/loads/Student.java new file mode 100644 index 0000000..2ae059c --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/loads/Student.java @@ -0,0 +1,31 @@ +package haidnor.jvm.test.instruction.loads; + +public class Student { + + public byte byteVal; + + public short shortVal; + + public float floatVal; + + public double doubleVal; + + public int intVal; + + public long longVal; + + public char charVal; + + public boolean booleanVal; + + public Student(byte byteVal, short shortVal, float floatVal, double doubleVal, int intVal, long longVal, char charVal, boolean booleanVal) { + this.byteVal = byteVal; + this.shortVal = shortVal; + this.floatVal = floatVal; + this.doubleVal = doubleVal; + this.intVal = intVal; + this.longVal = longVal; + this.charVal = charVal; + this.booleanVal = booleanVal; + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/loads/Student1.java b/src/test/java/haidnor/jvm/test/instruction/loads/Student1.java new file mode 100644 index 0000000..3a552a8 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/loads/Student1.java @@ -0,0 +1,13 @@ +package haidnor.jvm.test.instruction.loads; + +public class Student1 { + + public int a() { + return b(); + } + + public int b() { + return 233; + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/DADD.java b/src/test/java/haidnor/jvm/test/instruction/math/DADD.java new file mode 100644 index 0000000..34b8e7b --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/DADD.java @@ -0,0 +1,15 @@ +package haidnor.jvm.test.instruction.math; + +public class DADD { + + public static void main(String[] args) { + double c = add(1D, 2D); + System.out.println(c); + } + + public static double add(double a, double b) { + double c = a + b; + return c; + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/FADD.java b/src/test/java/haidnor/jvm/test/instruction/math/FADD.java new file mode 100644 index 0000000..94bf9fa --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/FADD.java @@ -0,0 +1,15 @@ +package haidnor.jvm.test.instruction.math; + +public class FADD { + + public static void main(String[] args) { + float c = add(1, 2); + System.out.println(c); + } + + public static float add(float a, float b) { + float c = a + b; + return c; + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/IADD.java b/src/test/java/haidnor/jvm/test/instruction/math/IADD.java new file mode 100644 index 0000000..e033ba7 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/IADD.java @@ -0,0 +1,15 @@ +package haidnor.jvm.test.instruction.math; + +public class IADD { + + public static void main(String[] args) { + int c = add(1, 2); + System.out.println(c); + } + + public static int add(int a, int b) { + int c = a + b; + return c; + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/IINC.java b/src/test/java/haidnor/jvm/test/instruction/math/IINC.java new file mode 100644 index 0000000..4396311 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/IINC.java @@ -0,0 +1,23 @@ +package haidnor.jvm.test.instruction.math; + +public class IINC { + + public static void main(String[] args) { + int a = -127; + a++; + System.out.println(a); + + int b = 129; + b++; + System.out.println(b); + + int c = 321; + c++; + System.out.println(c); + + int d = 0; + d++; + System.out.println(d); + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/ISUB.java b/src/test/java/haidnor/jvm/test/instruction/math/ISUB.java new file mode 100644 index 0000000..ebdc7a0 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/ISUB.java @@ -0,0 +1,10 @@ +package haidnor.jvm.test.instruction.math; + +public class ISUB { + public static void main(String[] args) { + int a = 2; + int b = 1; + int c = a - b; + System.out.println(c); + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/LADD.java b/src/test/java/haidnor/jvm/test/instruction/math/LADD.java new file mode 100644 index 0000000..dd3abb2 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/LADD.java @@ -0,0 +1,15 @@ +package haidnor.jvm.test.instruction.math; + +public class LADD { + + public static void main(String[] args) { + long c = add(1, 2); + System.out.println(c); + } + + public static long add(long a, long b) { + long c = a + b; + return c; + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/math/LSUB.java b/src/test/java/haidnor/jvm/test/instruction/math/LSUB.java new file mode 100644 index 0000000..dd65c37 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/math/LSUB.java @@ -0,0 +1,10 @@ +package haidnor.jvm.test.instruction.math; + +public class LSUB { + public static void main(String[] args) { + long a = 2000L; + long b = 1000L; + long c = a - b; + System.out.println(c); + } +} diff --git a/src/test/java/haidnor/jvm/test/instruction/references/CallStaticMethod.java b/src/test/java/haidnor/jvm/test/instruction/references/CallStaticMethod.java new file mode 100644 index 0000000..f32ff38 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/references/CallStaticMethod.java @@ -0,0 +1,14 @@ +package haidnor.jvm.test.instruction.references; + +public class CallStaticMethod { + + public static void main(String[] args) { + float i = staticMethod(); + System.out.println(i); + } + + public static float staticMethod() { + return 1321.321f; + } + +} diff --git a/src/test/java/haidnor/jvm/test/instruction/references/NEW.java b/src/test/java/haidnor/jvm/test/instruction/references/NEW.java new file mode 100644 index 0000000..746a5fb --- /dev/null +++ b/src/test/java/haidnor/jvm/test/instruction/references/NEW.java @@ -0,0 +1,21 @@ +package haidnor.jvm.test.instruction.references; + +import java.io.IOException; + +public class NEW { + + public static void main(String[] args) throws IOException { + add(1, 2, 3, 4, 5, 6, 7); + } + + public static void add(int a, int b, int c, int d, int e, int f, int g) { + System.out.println(a); + System.out.println(b); + System.out.println(c); + System.out.println(d); + System.out.println(e); + System.out.println(f); + System.out.println(g); + } + +} diff --git a/src/test/java/haidnor/jvm/test/model/Animal.java b/src/test/java/haidnor/jvm/test/model/Animal.java new file mode 100644 index 0000000..dbfa09c --- /dev/null +++ b/src/test/java/haidnor/jvm/test/model/Animal.java @@ -0,0 +1,5 @@ +package haidnor.jvm.test.model; + +public interface Animal { + +} diff --git a/src/test/java/haidnor/jvm/test/model/CustomClassLoader.java b/src/test/java/haidnor/jvm/test/model/CustomClassLoader.java new file mode 100644 index 0000000..f0d2b9e --- /dev/null +++ b/src/test/java/haidnor/jvm/test/model/CustomClassLoader.java @@ -0,0 +1,40 @@ +package haidnor.jvm.test.model; + +import java.io.FileNotFoundException; + +public class CustomClassLoader extends ClassLoader { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + + try { + byte[] result = getClassFromCustomPath(name); + if (result == null) { + throw new FileNotFoundException(); + } else { + //defineClass和findClass搭配使用 + return defineClass(name, result, 0, result.length); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + throw new ClassNotFoundException(name); + } + //自定义流的获取方式 + private byte[] getClassFromCustomPath(String name) { + //从自定义路径中加载指定类:细节略 + //如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作。 + return null; + } + + public static void main(String[] args) { + CustomClassLoader customClassLoader = new CustomClassLoader(); + try { + Class clazz = Class.forName("One", true, customClassLoader); + Object obj = clazz.newInstance(); + System.out.println(obj.getClass().getClassLoader()); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/test/java/haidnor/jvm/test/model/Demo.java b/src/test/java/haidnor/jvm/test/model/Demo.java new file mode 100644 index 0000000..8a72bd9 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/model/Demo.java @@ -0,0 +1,29 @@ +package haidnor.jvm.test.model; + +public class Demo { + + static { + System.out.println("类被加载了"); + } + + public static void main(String[] args) { + System.out.println("helloWorld"); + } + + public int add(int a, int b) { + return a + b; + } + + public int div(int a, int b) { + int c = 0; + try { + c = a / b; + } catch (Exception exception) { + throw new RuntimeException(); + } finally { + System.out.println("调用 div()"); + } + return c; + } + +} diff --git a/src/test/java/haidnor/jvm/test/model/Dog.java b/src/test/java/haidnor/jvm/test/model/Dog.java new file mode 100644 index 0000000..53b10b6 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/model/Dog.java @@ -0,0 +1,7 @@ +package haidnor.jvm.test.model; + +public abstract class Dog implements Animal { + static { + System.out.println("抽象狗类被加载了"); + } +} diff --git a/src/test/java/haidnor/jvm/test/model/DogTest.java b/src/test/java/haidnor/jvm/test/model/DogTest.java new file mode 100644 index 0000000..4d679d2 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/model/DogTest.java @@ -0,0 +1,15 @@ +package haidnor.jvm.test.model; + +public class DogTest { + + public static void main(String[] args) { + ThinDog dog1 = new ThinDog(); + if (dog1 instanceof Dog) { + System.out.println("细狗是一种狗"); + } + } + + static class InnerClass { + + } +} diff --git a/src/test/java/haidnor/jvm/test/model/ThinDog.java b/src/test/java/haidnor/jvm/test/model/ThinDog.java new file mode 100644 index 0000000..b30e5cd --- /dev/null +++ b/src/test/java/haidnor/jvm/test/model/ThinDog.java @@ -0,0 +1,13 @@ +package haidnor.jvm.test.model; + +/** + * + * (\,------------------'()'--o + * (_ ______________ ___/~" + * (_)_) (_)_) + */ +public class ThinDog extends Dog { + static { + System.out.println("细狗类被加载了"); + } +}