diff --git a/src/main/java/haidnor/jvm/core/Interpreter.java b/src/main/java/haidnor/jvm/core/Interpreter.java index 1961d2b..4f56f94 100644 --- a/src/main/java/haidnor/jvm/core/Interpreter.java +++ b/src/main/java/haidnor/jvm/core/Interpreter.java @@ -19,30 +19,30 @@ import java.util.Map; @Slf4j public class Interpreter { - private static int frameCount = -1; - @SneakyThrows public static void executeFrame(Frame frame) { - frameCount++; + int stackSize = frame.getJvmThread().stackSize(); + StringBuilder blank = new StringBuilder(); - blank.append(" ".repeat(Math.max(0, frameCount))); + blank.append(" ".repeat(stackSize - 1)); int index = 0; - for (int i = 0; i < frameCount; i++) { + for (int i = 0; i < stackSize - 1; i++) { blank.replace(index, index + 1, "│"); index += 20; } - log.debug("{}┌──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod()); - Map instructionMap = new HashMap<>(); + log.debug("{}┌──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod()); // 解析方法中的字节码指令 + Map instructionMap = new HashMap<>(); CodeStream codeStream = frame.getCodeStream(); while (codeStream.available() > 0) { Instruction instruction = InstructionFactory.creatInstruction(codeStream); - // log.debug("{}│>{}", blank, instruction); + log.debug("{}│> {}", blank, instruction); instructionMap.put(instruction.index(), instruction); } - // log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank); + + log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank); // 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“) for (int i = 0; i < frame.getCodeLength(); ) { @@ -54,8 +54,8 @@ public class Interpreter { } i += instruction.offSet(); } - log.debug("{}└──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod()); - frameCount--; + + log.debug("{}└──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod()); } } \ No newline at end of file diff --git a/src/main/java/haidnor/jvm/instruction/Instruction.java b/src/main/java/haidnor/jvm/instruction/Instruction.java index dd25027..98cca0d 100644 --- a/src/main/java/haidnor/jvm/instruction/Instruction.java +++ b/src/main/java/haidnor/jvm/instruction/Instruction.java @@ -3,6 +3,9 @@ package haidnor.jvm.instruction; import haidnor.jvm.runtime.Frame; import haidnor.jvm.util.CodeStream; +/** + * @author wang xiang + */ public abstract class Instruction { /** * 指令坐在 code 数组中的索引下标 @@ -10,7 +13,7 @@ public abstract class Instruction { private final int index; /** - * 执行下一个执行的偏移量 + * 执行下一个指令的偏移量 */ private int offSet = 1; diff --git a/src/main/java/haidnor/jvm/instruction/InstructionFactory.java b/src/main/java/haidnor/jvm/instruction/InstructionFactory.java index 742ebd8..5534301 100644 --- a/src/main/java/haidnor/jvm/instruction/InstructionFactory.java +++ b/src/main/java/haidnor/jvm/instruction/InstructionFactory.java @@ -598,7 +598,7 @@ public abstract class InstructionFactory { return new CHECKCAST(codeStream); } case Const.INSTANCEOF -> { - throw new Error("Not support JavaVM opcode INSTANCEOF"); + return new INSTANCEOF(codeStream); } case Const.MONITORENTER -> { throw new Error("Not support JavaVM opcode MONITORENTER"); 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..3ed1376 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java @@ -0,0 +1,56 @@ +package haidnor.jvm.instruction.references; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.rtda.heap.Instance; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import haidnor.jvm.util.ConstantPoolUtil; +import lombok.SneakyThrows; +import org.apache.bcel.Const; +import org.apache.bcel.classfile.ConstantClass; +import org.apache.bcel.classfile.ConstantPool; +import org.apache.bcel.classfile.Utility; + +/** + * @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.getConstantPool(); + ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil(); + ConstantClass constantClass = constantPool.getConstant(constantClassIndex); + String className = constantPoolUtil.getClassName(constantClass); + className = Utility.compactClassName(className); + + StackValue stackValue = frame.pop(); + Object obj = stackValue.getValue(); + Class objClass = obj.getClass(); + + if (obj instanceof Instance instance) { + String instanceClassName = instance.klass.getClassName(); + if (instanceClassName.equals(className)) { + frame.push(new StackValue(Const.T_INT, 1)); + } else { + frame.push(new StackValue(Const.T_INT, 0)); + } + } else { + if (objClass.getName().equals(className)) { + frame.push(new StackValue(Const.T_INT, 1)); + } else { + frame.push(new StackValue(Const.T_INT, 0)); + } + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java b/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java index f8dfa7d..96a1b90 100644 --- a/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE.java @@ -1,7 +1,6 @@ package haidnor.jvm.instruction.stores; import haidnor.jvm.instruction.Instruction; -import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.StackValue; import haidnor.jvm.util.CodeStream; @@ -18,7 +17,7 @@ public class ASTORE extends Instruction { @Override public void execute(Frame frame) { StackValue value = frame.pop(); - frame.slotSetRef(index, (Instance) value.getValue()); + 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 index 19d39ad..930ba45 100644 --- a/src/main/java/haidnor/jvm/instruction/stores/ASTORE_0.java +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_0.java @@ -1,7 +1,6 @@ package haidnor.jvm.instruction.stores; import haidnor.jvm.instruction.Instruction; -import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.StackValue; import haidnor.jvm.util.CodeStream; @@ -15,7 +14,7 @@ public class ASTORE_0 extends Instruction { @Override public void execute(Frame frame) { StackValue value = frame.pop(); - frame.slotSetRef(0, (Instance) value.getValue()); + frame.slotSetRef(0, 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 index 0ea75d6..966d894 100644 --- a/src/main/java/haidnor/jvm/instruction/stores/ASTORE_3.java +++ b/src/main/java/haidnor/jvm/instruction/stores/ASTORE_3.java @@ -1,7 +1,6 @@ package haidnor.jvm.instruction.stores; import haidnor.jvm.instruction.Instruction; -import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.StackValue; import haidnor.jvm.util.CodeStream; @@ -15,7 +14,7 @@ public class ASTORE_3 extends Instruction { @Override public void execute(Frame frame) { StackValue value = frame.pop(); - frame.slotSetRef(3, (Instance) value.getValue()); + frame.slotSetRef(3, value.getValue()); } } diff --git a/src/main/java/haidnor/jvm/runtime/Frame.java b/src/main/java/haidnor/jvm/runtime/Frame.java index 4db8136..186af2c 100644 --- a/src/main/java/haidnor/jvm/runtime/Frame.java +++ b/src/main/java/haidnor/jvm/runtime/Frame.java @@ -33,7 +33,7 @@ public class Frame { private final KlassMethod klassMethod; - public final Klass aKlass; + public final Klass klass; /** * 栈帧所属的方法代码对象 @@ -63,7 +63,7 @@ public class Frame { public Frame(JvmThread jvmThread, KlassMethod klassMethod) { this.jvmThread = jvmThread; - this.aKlass = klassMethod.aKlass; + this.klass = klassMethod.aKlass; this.klassMethod = klassMethod; this.method = klassMethod.javaMethod; this.code = method.getCode(); @@ -103,7 +103,7 @@ public class Frame { } public Klass getMetaClass() { - return aKlass; + return klass; } /* 操作数栈操作 --------------------------------------------------------------------------------------------------- */ diff --git a/src/test/java/haidnor/jvm/test/TestJVM.java b/src/test/java/haidnor/jvm/test/TestJVM.java index e8c2386..ecc7ad8 100644 --- a/src/test/java/haidnor/jvm/test/TestJVM.java +++ b/src/test/java/haidnor/jvm/test/TestJVM.java @@ -59,6 +59,11 @@ public class TestJVM { runMainClass(Demo5.class); } + @Test + public void test_6() throws Exception { + runMainClass(Demo6.class); + } + @Test public void test_NEW() throws Exception { runMainClass(NEW.class); diff --git a/src/test/java/haidnor/jvm/test/demo/Demo3.java b/src/test/java/haidnor/jvm/test/demo/Demo3.java index 69ef2a0..97b40ca 100644 --- a/src/test/java/haidnor/jvm/test/demo/Demo3.java +++ b/src/test/java/haidnor/jvm/test/demo/Demo3.java @@ -11,7 +11,7 @@ public class Demo3 { Student sut2 = new Student(); HashMap hashMap = new HashMap<>(); - hashMap.put(sut1, "张三"); + hashMap.put(sut1, "张三123"); hashMap.put(sut2, "张三"); System.out.println(hashMap.get(sut1)); // 1 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..2869007 --- /dev/null +++ b/src/test/java/haidnor/jvm/test/demo/Demo6.java @@ -0,0 +1,15 @@ +package haidnor.jvm.test.demo; + + +import haidnor.jvm.test.clazz.Student; + +public class Demo6 { + + public static void main(String[] args) { + Student student = new Student(); + if (student instanceof Student) { + System.out.println("instanceof"); + } + } + +}