update INVOKEVIRTUAL

This commit is contained in:
wangxiang
2023-07-20 10:39:05 +08:00
parent ff0fcd92bd
commit 51623e505c
5 changed files with 55 additions and 31 deletions

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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冲突
}
}

View File

@@ -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();
}
}