mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-03-23 21:33:43 +08:00
update INVOKEVIRTUAL
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
package haidnor.jvm.instruction.references;
|
package haidnor.jvm.instruction.references;
|
||||||
|
|
||||||
|
import haidnor.jvm.classloader.ClassLoader;
|
||||||
import haidnor.jvm.core.JavaExecutionEngine;
|
import haidnor.jvm.core.JavaExecutionEngine;
|
||||||
import haidnor.jvm.instruction.Instruction;
|
import haidnor.jvm.instruction.Instruction;
|
||||||
import haidnor.jvm.rtda.heap.Instance;
|
|
||||||
import haidnor.jvm.rtda.heap.Klass;
|
import haidnor.jvm.rtda.heap.Klass;
|
||||||
import haidnor.jvm.rtda.heap.KlassMethod;
|
import haidnor.jvm.rtda.heap.KlassMethod;
|
||||||
|
import haidnor.jvm.rtda.metaspace.Metaspace;
|
||||||
import haidnor.jvm.runtime.Frame;
|
import haidnor.jvm.runtime.Frame;
|
||||||
import haidnor.jvm.runtime.StackValue;
|
import haidnor.jvm.runtime.StackValue;
|
||||||
import haidnor.jvm.util.CodeStream;
|
import haidnor.jvm.util.CodeStream;
|
||||||
@@ -76,20 +77,42 @@ public class INVOKEVIRTUAL extends Instruction {
|
|||||||
}
|
}
|
||||||
// 调用自定义类的方法
|
// 调用自定义类的方法
|
||||||
else {
|
else {
|
||||||
// 获得栈顶对象实例,根据对象的实际类型进行分派(虚方法分派),支持多态
|
Klass klass = Metaspace.getJavaClass(Utility.compactClassName(className));
|
||||||
StackValue stackValue = frame.peek();
|
JavaClass javaClass;
|
||||||
Instance instance = (Instance) stackValue.getValue();
|
if (klass != null) {
|
||||||
Klass meteKlass = instance.klass;
|
javaClass = klass.getJavaClass();
|
||||||
JavaClass javaClass = meteKlass.getJavaClass();
|
} else {
|
||||||
for (org.apache.bcel.classfile.Method method : javaClass.getMethods()) {
|
ClassLoader classLoader = frame.getMetaClass().getClassLoader();
|
||||||
if (method.getSignature().equals(methodSignature) && method.getName().equals(methodName)) {
|
klass = classLoader.loadClass(className);
|
||||||
KlassMethod klassMethod = new KlassMethod(meteKlass, method);
|
javaClass = klass.getJavaClass();
|
||||||
JavaExecutionEngine.callMethod(frame, klassMethod);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import haidnor.jvm.runtime.JvmThread;
|
|||||||
import haidnor.jvm.test.demo.Demo1;
|
import haidnor.jvm.test.demo.Demo1;
|
||||||
import haidnor.jvm.test.demo.Demo2;
|
import haidnor.jvm.test.demo.Demo2;
|
||||||
import haidnor.jvm.test.demo.Demo3;
|
import haidnor.jvm.test.demo.Demo3;
|
||||||
|
import haidnor.jvm.test.demo.Demo4;
|
||||||
import haidnor.jvm.test.instruction.Array;
|
import haidnor.jvm.test.instruction.Array;
|
||||||
import haidnor.jvm.test.instruction.DO_WHILE;
|
import haidnor.jvm.test.instruction.DO_WHILE;
|
||||||
import haidnor.jvm.test.instruction.math.ISUB;
|
import haidnor.jvm.test.instruction.math.ISUB;
|
||||||
@@ -51,6 +52,11 @@ public class TestJVM {
|
|||||||
runMainClass(Demo3.class);
|
runMainClass(Demo3.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_4() throws Exception {
|
||||||
|
runMainClass(Demo4.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_NEW() throws Exception {
|
public void test_NEW() throws Exception {
|
||||||
runMainClass(NEW.class);
|
runMainClass(NEW.class);
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
package haidnor.jvm.test.clazz;
|
package haidnor.jvm.test.clazz;
|
||||||
|
|
||||||
public class Student implements Person {
|
public class Student extends Baby{
|
||||||
|
|
||||||
@Override
|
private int age;
|
||||||
public void eat() {
|
|
||||||
System.out.println("学生只能在学校食堂吃饭");
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,17 +30,5 @@ class Student {
|
|||||||
this.age = age;
|
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冲突
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package haidnor.jvm.test.demo;
|
package haidnor.jvm.test.demo;
|
||||||
|
|
||||||
|
import haidnor.jvm.test.clazz.Student;
|
||||||
|
|
||||||
public class Demo4 {
|
public class Demo4 {
|
||||||
|
|
||||||
public static String str = "ABC";
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// System.out.println(Demo3.str == Demo4.str); // true
|
Student student = new Student();
|
||||||
|
student.eat();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user