diff --git a/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java b/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java index 04fefc3..e8f86dd 100644 --- a/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java +++ b/src/main/java/haidnor/jvm/core/JavaExecutionEngine.java @@ -112,7 +112,7 @@ public class JavaExecutionEngine { frame.push(new StackValue(Const.T_OBJECT, exception)); handlerPC = codeException.getHandlerPC(); } else { - String exceptionClassName = frame.getConstantPoolUtil().getConstantClassClassName(catchType); + String exceptionClassName = frame.getConstantPoolUtil().constantClass_ClassName(catchType); exceptionClassName = Utility.compactClassName(exceptionClassName, false); Class exceptionClass = Class.forName(exceptionClassName); if (exceptionClass.isAssignableFrom(exception.getClass())) { diff --git a/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java b/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java index f283597..fc5c18c 100644 --- a/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java +++ b/src/main/java/haidnor/jvm/instruction/references/ANEWARRAY.java @@ -8,11 +8,8 @@ import haidnor.jvm.rtda.Metaspace; 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; public class ANEWARRAY extends Instruction { @@ -27,10 +24,7 @@ public class ANEWARRAY extends Instruction { @Override @SneakyThrows public void execute(Frame frame) { - ConstantPool constantPool = frame.getConstantPool(); - ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil(); - ConstantClass constantClass = constantPool.getConstant(constantClassIndex); - String className = constantPoolUtil.getConstantClassClassName(constantClass); + String className = frame.getConstantPoolUtil().constantClass_ClassName(constantClassIndex); Klass klass = Metaspace.getJavaClass(Utility.compactClassName(className)); if (klass == null) { diff --git a/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java b/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java index 6cd3617..156b7e5 100644 --- a/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java +++ b/src/main/java/haidnor/jvm/instruction/references/GETSTATIC.java @@ -37,7 +37,7 @@ public class GETSTATIC extends Instruction { ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil(); ConstantFieldref constFieldref = constantPool.getConstant(constantFieldrefIndex); // 动态链接. 找到字段所属的 Java 类 - String className = constantPoolUtil.getFiledBelongClassName(constFieldref); + String className = constantPoolUtil.constantFieldref_ClassName(constFieldref); // 动态链接. 找到字段的名字 String fieldName = constantPoolUtil.getFieldName(constFieldref); // 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数. diff --git a/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java b/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java index 5987438..c730dbc 100644 --- a/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java +++ b/src/main/java/haidnor/jvm/instruction/references/INSTANCEOF.java @@ -8,8 +8,7 @@ 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.JavaClass; import org.apache.bcel.classfile.Utility; /** @@ -27,10 +26,9 @@ public class INSTANCEOF extends Instruction { @Override @SneakyThrows public void execute(Frame frame) { - ConstantPool constantPool = frame.getConstantPool(); ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil(); - ConstantClass constantClass = constantPool.getConstant(constantClassIndex); - String className = constantPoolUtil.getConstantClassClassName(constantClass); + + String className = constantPoolUtil.constantClass_ClassName(constantClassIndex); className = Utility.compactClassName(className); StackValue stackValue = frame.pop(); @@ -38,14 +36,17 @@ public class INSTANCEOF extends Instruction { Class objClass = obj.getClass(); if (obj instanceof Instance instance) { - String instanceClassName = instance.klass.getClassName(); - if (instanceClassName.equals(className)) { + boolean result = findClassFromSuper(instance.klass.getJavaClass(), className); + if (!result) { + result = findClassFromInterface(instance.klass.getJavaClass(), className); + } + if (result) { frame.push(new StackValue(Const.T_INT, 1)); } else { frame.push(new StackValue(Const.T_INT, 0)); } } else { - if (objClass.getName().equals(className)) { + if (Class.forName(className).isAssignableFrom(objClass)) { frame.push(new StackValue(Const.T_INT, 1)); } else { frame.push(new StackValue(Const.T_INT, 0)); @@ -53,4 +54,25 @@ public class INSTANCEOF extends Instruction { } } + 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/INVOKEINTERFACE.java b/src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java index d583bda..946d9e1 100644 --- a/src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKEINTERFACE.java @@ -47,7 +47,7 @@ public class INVOKEINTERFACE extends Instruction { ConstantInterfaceMethodref interfaceMethodref = constantPool.getConstant(constantMethodrefIndex); int classIndex = interfaceMethodref.getClassIndex(); - String interfaceName = constantPoolUtil.getConstantClassClassName(classIndex); + String interfaceName = constantPoolUtil.constantClass_ClassName(classIndex); int nameAndTypeIndex = interfaceMethodref.getNameAndTypeIndex(); String methodName = constantPoolUtil.constantNameAndType_name(nameAndTypeIndex); diff --git a/src/main/java/haidnor/jvm/instruction/references/NEW.java b/src/main/java/haidnor/jvm/instruction/references/NEW.java index 632709b..530ed88 100644 --- a/src/main/java/haidnor/jvm/instruction/references/NEW.java +++ b/src/main/java/haidnor/jvm/instruction/references/NEW.java @@ -10,8 +10,6 @@ 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; public class NEW extends Instruction { @@ -26,10 +24,8 @@ public class NEW extends Instruction { @Override @SneakyThrows public void execute(Frame frame) { - ConstantPool constantPool = frame.getConstantPool(); ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil(); - ConstantClass constantClass = constantPool.getConstant(constantClassIndex); - String className = constantPoolUtil.getConstantClassClassName(constantClass); + String className = constantPoolUtil.constantClass_ClassName(constantClassIndex); if (className.startsWith("java/")) { frame.push(new StackValue(Const.T_OBJECT, null)); diff --git a/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java b/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java index ebbffcc..509a179 100644 --- a/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java +++ b/src/main/java/haidnor/jvm/instruction/references/PUTSTATIC.java @@ -31,7 +31,7 @@ public class PUTSTATIC extends Instruction { ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil(); ConstantFieldref constFieldref = constantPool.getConstant(constantFieldrefIndex); // 动态链接. 找到字段所属的 Java 类 - String className = constantPoolUtil.getFiledBelongClassName(constFieldref); + String className = constantPoolUtil.constantFieldref_ClassName(constFieldref); // 动态链接. 找到字段的名字 String fieldName = constantPoolUtil.getFieldName(constFieldref); // 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数. diff --git a/src/main/java/haidnor/jvm/util/ConstantPoolUtil.java b/src/main/java/haidnor/jvm/util/ConstantPoolUtil.java index 14a5f60..f6e6789 100644 --- a/src/main/java/haidnor/jvm/util/ConstantPoolUtil.java +++ b/src/main/java/haidnor/jvm/util/ConstantPoolUtil.java @@ -42,7 +42,7 @@ public class ConstantPoolUtil { /** * 获取长类名, 例如 java/lang/String */ - public String getConstantClassClassName(final ConstantClass constantClass) { + public String constantClass_ClassName(final ConstantClass constantClass) { ConstantUtf8 constantUtf8 = cp.getConstant(constantClass.getNameIndex()); return constantUtf8.getBytes(); } @@ -50,9 +50,9 @@ public class ConstantPoolUtil { /** * 获取长类名, 例如 java/lang/String */ - public String getConstantClassClassName(int constantClassIndex) { + public String constantClass_ClassName(int constantClassIndex) { ConstantClass constantClass = cp.getConstant(constantClassIndex); - return getConstantClassClassName(constantClass); + return constantClass_ClassName(constantClass); } @@ -61,7 +61,7 @@ public class ConstantPoolUtil { /** * 获取字段所处于Java类的类名, 例如 java/lang/String */ - public String getFiledBelongClassName(final ConstantFieldref constantFieldref) { + public String constantFieldref_ClassName(final ConstantFieldref constantFieldref) { ConstantClass constClass = cp.getConstant(constantFieldref.getClassIndex()); return (String) constClass.getConstantValue(cp); } @@ -69,9 +69,9 @@ public class ConstantPoolUtil { /** * 获取字段所处于Java类的类名, 例如 java/lang/String */ - public String getFiledBelongClassName(int constantFieldrefIndex) { + public String constantFieldref_ClassName(int constantFieldrefIndex) { ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex); - return getFiledBelongClassName(constantFieldref); + return constantFieldref_ClassName(constantFieldref); } /** diff --git a/src/test/java/haidnor/jvm/test/clazz/Student.java b/src/test/java/haidnor/jvm/test/clazz/Student.java index a6065a3..f393a22 100644 --- a/src/test/java/haidnor/jvm/test/clazz/Student.java +++ b/src/test/java/haidnor/jvm/test/clazz/Student.java @@ -1,6 +1,6 @@ package haidnor.jvm.test.clazz; -public class Student implements Organism { +public class Student extends Human implements Organism { public void method1() { System.out.println("method1"); diff --git a/src/test/java/haidnor/jvm/test/demo/Demo6.java b/src/test/java/haidnor/jvm/test/demo/Demo6.java index 2869007..751d337 100644 --- a/src/test/java/haidnor/jvm/test/demo/Demo6.java +++ b/src/test/java/haidnor/jvm/test/demo/Demo6.java @@ -1,14 +1,15 @@ 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 Student) { - System.out.println("instanceof"); + if (student instanceof Human) { + System.out.println("true"); } }