From 51623e505c1550dc2f2a9e45327a8decb731a33e Mon Sep 17 00:00:00 2001 From: wangxiang <276644985@qq.com> Date: Thu, 20 Jul 2023 10:39:05 +0800 Subject: [PATCH] update INVOKEVIRTUAL --- .../instruction/references/INVOKEVIRTUAL.java | 47 ++++++++++++++----- src/test/java/haidnor/jvm/test/TestJVM.java | 6 +++ .../java/haidnor/jvm/test/clazz/Student.java | 13 +++-- .../java/haidnor/jvm/test/demo/Demo3.java | 12 ----- .../java/haidnor/jvm/test/demo/Demo4.java | 8 ++-- 5 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java b/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java index 7f093b3..b23fd53 100644 --- a/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java +++ b/src/main/java/haidnor/jvm/instruction/references/INVOKEVIRTUAL.java @@ -1,10 +1,11 @@ package haidnor.jvm.instruction.references; +import haidnor.jvm.classloader.ClassLoader; import haidnor.jvm.core.JavaExecutionEngine; import haidnor.jvm.instruction.Instruction; -import haidnor.jvm.rtda.heap.Instance; import haidnor.jvm.rtda.heap.Klass; import haidnor.jvm.rtda.heap.KlassMethod; +import haidnor.jvm.rtda.metaspace.Metaspace; import haidnor.jvm.runtime.Frame; import haidnor.jvm.runtime.StackValue; import haidnor.jvm.util.CodeStream; @@ -76,20 +77,42 @@ public class INVOKEVIRTUAL extends Instruction { } // 调用自定义类的方法 else { - // 获得栈顶对象实例,根据对象的实际类型进行分派(虚方法分派),支持多态 - StackValue stackValue = frame.peek(); - Instance instance = (Instance) stackValue.getValue(); - Klass meteKlass = instance.klass; - JavaClass javaClass = meteKlass.getJavaClass(); - for (org.apache.bcel.classfile.Method method : javaClass.getMethods()) { - if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) { - KlassMethod klassMethod = new KlassMethod(meteKlass, method); - JavaExecutionEngine.callMethod(frame, klassMethod); - break; - } + Klass klass = Metaspace.getJavaClass(Utility.compactClassName(className)); + JavaClass javaClass; + if (klass != null) { + javaClass = klass.getJavaClass(); + } else { + ClassLoader classLoader = frame.getMetaClass().getClassLoader(); + klass = classLoader.loadClass(className); + javaClass = klass.getJavaClass(); } + + org.apache.bcel.classfile.Method method = getMethod(javaClass, methodSignature, methodName); + if (method == null) { + throw new NoSuchMethodException(); + } + KlassMethod klassMethod = new KlassMethod(klass, method); + JavaExecutionEngine.callMethod(frame, klassMethod); } } + /** + * 递归查找方法, 如果子类没有实现方法则向父类查找 + */ + private static org.apache.bcel.classfile.Method getMethod(JavaClass javaClass, String methodSignature,String methodName) throws ClassNotFoundException { + org.apache.bcel.classfile.Method m = null; + for (org.apache.bcel.classfile.Method 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/test/java/haidnor/jvm/test/TestJVM.java b/src/test/java/haidnor/jvm/test/TestJVM.java index 6e11e46..1aa577f 100644 --- a/src/test/java/haidnor/jvm/test/TestJVM.java +++ b/src/test/java/haidnor/jvm/test/TestJVM.java @@ -9,6 +9,7 @@ import haidnor.jvm.runtime.JvmThread; import haidnor.jvm.test.demo.Demo1; import haidnor.jvm.test.demo.Demo2; import haidnor.jvm.test.demo.Demo3; +import haidnor.jvm.test.demo.Demo4; import haidnor.jvm.test.instruction.Array; import haidnor.jvm.test.instruction.DO_WHILE; import haidnor.jvm.test.instruction.math.ISUB; @@ -51,6 +52,11 @@ public class TestJVM { runMainClass(Demo3.class); } + @Test + public void test_4() throws Exception { + runMainClass(Demo4.class); + } + @Test public void test_NEW() throws Exception { runMainClass(NEW.class); diff --git a/src/test/java/haidnor/jvm/test/clazz/Student.java b/src/test/java/haidnor/jvm/test/clazz/Student.java index 96f9f83..98a377e 100644 --- a/src/test/java/haidnor/jvm/test/clazz/Student.java +++ b/src/test/java/haidnor/jvm/test/clazz/Student.java @@ -1,10 +1,15 @@ package haidnor.jvm.test.clazz; -public class Student implements Person { +public class Student extends Baby{ - @Override - public void eat() { - System.out.println("学生只能在学校食堂吃饭"); + private int age; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; } } diff --git a/src/test/java/haidnor/jvm/test/demo/Demo3.java b/src/test/java/haidnor/jvm/test/demo/Demo3.java index 0df013c..70aa83f 100644 --- a/src/test/java/haidnor/jvm/test/demo/Demo3.java +++ b/src/test/java/haidnor/jvm/test/demo/Demo3.java @@ -30,17 +30,5 @@ class Student { this.age = age; } -// @Override -// public boolean equals(Object o) { -// Student student = (Student) o; -// System.out.println("调用了 equals 方法, 将 age=" + age + " 与 age=" + student.age + " 的对象进行比较"); -// return age == student.age; -// } - - @Override - public int hashCode() { - System.out.println("调用了 hashCode 方法"); - return 123; // 这个 hashCode() 算法很糟糕, 100% hash冲突 - } } diff --git a/src/test/java/haidnor/jvm/test/demo/Demo4.java b/src/test/java/haidnor/jvm/test/demo/Demo4.java index 0bb3e44..c5255ce 100644 --- a/src/test/java/haidnor/jvm/test/demo/Demo4.java +++ b/src/test/java/haidnor/jvm/test/demo/Demo4.java @@ -1,10 +1,12 @@ package haidnor.jvm.test.demo; +import haidnor.jvm.test.clazz.Student; + public class Demo4 { - public static String str = "ABC"; - public static void main(String[] args) { -// System.out.println(Demo3.str == Demo4.str); // true + Student student = new Student(); + student.eat(); } + }