mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-03-13 21:43:42 +08:00
add Instruction
This commit is contained in:
@@ -19,30 +19,30 @@ import java.util.Map;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class Interpreter {
|
public class Interpreter {
|
||||||
|
|
||||||
private static int frameCount = -1;
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void executeFrame(Frame frame) {
|
public static void executeFrame(Frame frame) {
|
||||||
frameCount++;
|
int stackSize = frame.getJvmThread().stackSize();
|
||||||
|
|
||||||
StringBuilder blank = new StringBuilder();
|
StringBuilder blank = new StringBuilder();
|
||||||
blank.append(" ".repeat(Math.max(0, frameCount)));
|
blank.append(" ".repeat(stackSize - 1));
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (int i = 0; i < frameCount; i++) {
|
for (int i = 0; i < stackSize - 1; i++) {
|
||||||
blank.replace(index, index + 1, "│");
|
blank.replace(index, index + 1, "│");
|
||||||
index += 20;
|
index += 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("{}┌──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod());
|
log.debug("{}┌──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
|
||||||
Map<Integer, Instruction> instructionMap = new HashMap<>();
|
|
||||||
|
|
||||||
// 解析方法中的字节码指令
|
// 解析方法中的字节码指令
|
||||||
|
Map<Integer, Instruction> instructionMap = new HashMap<>();
|
||||||
CodeStream codeStream = frame.getCodeStream();
|
CodeStream codeStream = frame.getCodeStream();
|
||||||
while (codeStream.available() > 0) {
|
while (codeStream.available() > 0) {
|
||||||
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
|
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
|
||||||
// log.debug("{}│>{}", blank, instruction);
|
log.debug("{}│> {}", blank, instruction);
|
||||||
instructionMap.put(instruction.index(), instruction);
|
instructionMap.put(instruction.index(), instruction);
|
||||||
}
|
}
|
||||||
// log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
|
|
||||||
|
log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
|
||||||
|
|
||||||
// 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
|
// 执行方法中的字节码指令 tip:(int i, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
|
||||||
for (int i = 0; i < frame.getCodeLength(); ) {
|
for (int i = 0; i < frame.getCodeLength(); ) {
|
||||||
@@ -54,8 +54,8 @@ public class Interpreter {
|
|||||||
}
|
}
|
||||||
i += instruction.offSet();
|
i += instruction.offSet();
|
||||||
}
|
}
|
||||||
log.debug("{}└──────────────────[{}] {} | {} ", blank, frameCount + 1, frame.aKlass.getClassName(), frame.getMethod());
|
|
||||||
frameCount--;
|
log.debug("{}└──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,9 @@ package haidnor.jvm.instruction;
|
|||||||
import haidnor.jvm.runtime.Frame;
|
import haidnor.jvm.runtime.Frame;
|
||||||
import haidnor.jvm.util.CodeStream;
|
import haidnor.jvm.util.CodeStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author wang xiang
|
||||||
|
*/
|
||||||
public abstract class Instruction {
|
public abstract class Instruction {
|
||||||
/**
|
/**
|
||||||
* 指令坐在 code 数组中的索引下标
|
* 指令坐在 code 数组中的索引下标
|
||||||
@@ -10,7 +13,7 @@ public abstract class Instruction {
|
|||||||
private final int index;
|
private final int index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行下一个执行的偏移量
|
* 执行下一个指令的偏移量
|
||||||
*/
|
*/
|
||||||
private int offSet = 1;
|
private int offSet = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -598,7 +598,7 @@ public abstract class InstructionFactory {
|
|||||||
return new CHECKCAST(codeStream);
|
return new CHECKCAST(codeStream);
|
||||||
}
|
}
|
||||||
case Const.INSTANCEOF -> {
|
case Const.INSTANCEOF -> {
|
||||||
throw new Error("Not support JavaVM opcode INSTANCEOF");
|
return new INSTANCEOF(codeStream);
|
||||||
}
|
}
|
||||||
case Const.MONITORENTER -> {
|
case Const.MONITORENTER -> {
|
||||||
throw new Error("Not support JavaVM opcode MONITORENTER");
|
throw new Error("Not support JavaVM opcode MONITORENTER");
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package haidnor.jvm.instruction.stores;
|
package haidnor.jvm.instruction.stores;
|
||||||
|
|
||||||
import haidnor.jvm.instruction.Instruction;
|
import haidnor.jvm.instruction.Instruction;
|
||||||
import haidnor.jvm.rtda.heap.Instance;
|
|
||||||
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;
|
||||||
@@ -18,7 +17,7 @@ public class ASTORE extends Instruction {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Frame frame) {
|
public void execute(Frame frame) {
|
||||||
StackValue value = frame.pop();
|
StackValue value = frame.pop();
|
||||||
frame.slotSetRef(index, (Instance) value.getValue());
|
frame.slotSetRef(index, value.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package haidnor.jvm.instruction.stores;
|
package haidnor.jvm.instruction.stores;
|
||||||
|
|
||||||
import haidnor.jvm.instruction.Instruction;
|
import haidnor.jvm.instruction.Instruction;
|
||||||
import haidnor.jvm.rtda.heap.Instance;
|
|
||||||
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;
|
||||||
@@ -15,7 +14,7 @@ public class ASTORE_0 extends Instruction {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Frame frame) {
|
public void execute(Frame frame) {
|
||||||
StackValue value = frame.pop();
|
StackValue value = frame.pop();
|
||||||
frame.slotSetRef(0, (Instance) value.getValue());
|
frame.slotSetRef(0, value.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package haidnor.jvm.instruction.stores;
|
package haidnor.jvm.instruction.stores;
|
||||||
|
|
||||||
import haidnor.jvm.instruction.Instruction;
|
import haidnor.jvm.instruction.Instruction;
|
||||||
import haidnor.jvm.rtda.heap.Instance;
|
|
||||||
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;
|
||||||
@@ -15,7 +14,7 @@ public class ASTORE_3 extends Instruction {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Frame frame) {
|
public void execute(Frame frame) {
|
||||||
StackValue value = frame.pop();
|
StackValue value = frame.pop();
|
||||||
frame.slotSetRef(3, (Instance) value.getValue());
|
frame.slotSetRef(3, value.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class Frame {
|
|||||||
|
|
||||||
private final KlassMethod klassMethod;
|
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) {
|
public Frame(JvmThread jvmThread, KlassMethod klassMethod) {
|
||||||
this.jvmThread = jvmThread;
|
this.jvmThread = jvmThread;
|
||||||
this.aKlass = klassMethod.aKlass;
|
this.klass = klassMethod.aKlass;
|
||||||
this.klassMethod = klassMethod;
|
this.klassMethod = klassMethod;
|
||||||
this.method = klassMethod.javaMethod;
|
this.method = klassMethod.javaMethod;
|
||||||
this.code = method.getCode();
|
this.code = method.getCode();
|
||||||
@@ -103,7 +103,7 @@ public class Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Klass getMetaClass() {
|
public Klass getMetaClass() {
|
||||||
return aKlass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 操作数栈操作 --------------------------------------------------------------------------------------------------- */
|
/* 操作数栈操作 --------------------------------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ public class TestJVM {
|
|||||||
runMainClass(Demo5.class);
|
runMainClass(Demo5.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_6() throws Exception {
|
||||||
|
runMainClass(Demo6.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_NEW() throws Exception {
|
public void test_NEW() throws Exception {
|
||||||
runMainClass(NEW.class);
|
runMainClass(NEW.class);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class Demo3 {
|
|||||||
Student sut2 = new Student();
|
Student sut2 = new Student();
|
||||||
|
|
||||||
HashMap<Student, String> hashMap = new HashMap<>();
|
HashMap<Student, String> hashMap = new HashMap<>();
|
||||||
hashMap.put(sut1, "张三");
|
hashMap.put(sut1, "张三123");
|
||||||
hashMap.put(sut2, "张三");
|
hashMap.put(sut2, "张三");
|
||||||
|
|
||||||
System.out.println(hashMap.get(sut1)); // 1
|
System.out.println(hashMap.get(sut1)); // 1
|
||||||
|
|||||||
15
src/test/java/haidnor/jvm/test/demo/Demo6.java
Normal file
15
src/test/java/haidnor/jvm/test/demo/Demo6.java
Normal file
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user