mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-03-13 13:33:42 +08:00
update JavaExecutionEngine.java
This commit is contained in:
@@ -26,10 +26,19 @@ import java.util.Map;
|
||||
@Slf4j
|
||||
public class JavaExecutionEngine {
|
||||
|
||||
/**
|
||||
* 执行 public static void main(String[] args) 方法
|
||||
*/
|
||||
public static void callMainMethod(KlassMethod klassMethod) {
|
||||
callMethod(null, klassMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行普通方法
|
||||
*
|
||||
* @param lastFrame 方法调用者的栈帧
|
||||
* @param klassMethod 方法元信息
|
||||
*/
|
||||
public static void callMethod(Frame lastFrame, KlassMethod klassMethod) {
|
||||
JVMThread jvmThread = JvmThreadHolder.get();
|
||||
Frame newFrame = new Frame(jvmThread, klassMethod);
|
||||
@@ -80,26 +89,28 @@ public class JavaExecutionEngine {
|
||||
CodeStream codeStream = frame.getCodeStream();
|
||||
while (codeStream.available() > 0) {
|
||||
Instruction instruction = InstructionFactory.creatInstruction(codeStream);
|
||||
log.debug("{}│> {}", blank, instruction);
|
||||
instructionMap.put(instruction.index(), instruction);
|
||||
log.debug("{}│> {}", blank, instruction);
|
||||
}
|
||||
|
||||
log.debug("{}├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌", blank);
|
||||
|
||||
// 执行方法中的字节码指令 tip:(int pc, 相当于程序计数器, 记录当前执行到的字节码指令的”行号“)
|
||||
// 执行方法中的字节码指令
|
||||
// 提示: 变量 pc 相当于程序计数器, 记录当前执行到的字节码指令的"行号"
|
||||
for (int pc = 0; pc < frame.getCodeLength(); ) {
|
||||
Instruction instruction = instructionMap.get(pc);
|
||||
log.debug("{}│ {}", blank, instruction);
|
||||
try {
|
||||
// 执行栈帧
|
||||
// 执行字节码指令
|
||||
instruction.execute(frame);
|
||||
// 若为 return 系列指令则结束当前栈帧
|
||||
if (instruction instanceof RETURN || instruction instanceof ARETURN || instruction instanceof DRETURN || instruction instanceof FRETURN || instruction instanceof IRETURN) {
|
||||
break;
|
||||
}
|
||||
// 程序计数器值增加. 指向下一次执行的字节码行号
|
||||
pc += instruction.offSet();
|
||||
}
|
||||
// 捕获执行栈帧运行抛出的异常
|
||||
// 捕获执行字节码指令抛出的异常
|
||||
catch (Exception exception) {
|
||||
// 从类元信息中获取异常表
|
||||
CodeException[] exceptionTable = frame.getMethod().getCode().getExceptionTable();
|
||||
@@ -107,9 +118,9 @@ public class JavaExecutionEngine {
|
||||
// handlerPC 是从异常表中获取的处理异常的字节码行号 (如果查询不到就会一直为 null. 代表方法无异常处理代码)
|
||||
Integer handlerPC = null;
|
||||
for (CodeException codeException : exceptionTable) {
|
||||
if (codeException.getStartPC() <= pc & pc <= codeException.getEndPC()) {
|
||||
if (codeException.getStartPC() <= pc && pc <= codeException.getEndPC()) {
|
||||
// 异常类型 (0 代表捕获所有类型的异常)
|
||||
int catchType = codeException.getCatchType();
|
||||
// catchType == 0 代表捕获所有类型的异常
|
||||
if (catchType == 0) {
|
||||
frame.push(new StackValue(Const.T_OBJECT, exception));
|
||||
handlerPC = codeException.getHandlerPC();
|
||||
@@ -128,7 +139,7 @@ public class JavaExecutionEngine {
|
||||
// 将程序计数器跳转到处理异常的字节码指令上
|
||||
pc = handlerPC;
|
||||
} else {
|
||||
// 方法无异常处理. 异常退出.结束栈帧
|
||||
// 方法无异常处理,结束栈帧. 将异常抛给调用者处理
|
||||
log.debug("{}└──────────────────[{}] No Exception Handler Return!", blank, stackSize);
|
||||
throw exception;
|
||||
}
|
||||
@@ -141,9 +152,9 @@ public class JavaExecutionEngine {
|
||||
|
||||
/**
|
||||
* 计算绘画 jvm 线程栈 debug 日志信息的空格
|
||||
* 用于表现栈的调用关系.
|
||||
* 用于表现栈的调用关系
|
||||
*
|
||||
* @param stackSize 当前 JVM 栈的深度
|
||||
* @param stackSize 当前 JVM 线程栈的栈帧数量
|
||||
*/
|
||||
private static String getDebugStackInfoBlank(int stackSize) {
|
||||
StringBuilder blank = new StringBuilder();
|
||||
|
||||
@@ -8,7 +8,7 @@ import haidnor.jvm.util.CodeStream;
|
||||
*/
|
||||
public abstract class Instruction {
|
||||
/**
|
||||
* 指令坐在 code 数组中的索引下标
|
||||
* 指令在字节码 code 数组中的索引下标 (可以理解为指令的行号)
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
@@ -21,6 +21,11 @@ public abstract class Instruction {
|
||||
this.index = codeStream.index();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行执行
|
||||
*
|
||||
* @param frame 当前 JVM 线程栈的栈帧
|
||||
*/
|
||||
public abstract void execute(Frame frame);
|
||||
|
||||
public int index() {
|
||||
|
||||
@@ -26,6 +26,9 @@ public class JVMThread extends Thread {
|
||||
this.stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 JVM 线程栈的栈帧数量
|
||||
*/
|
||||
public int stackSize() {
|
||||
return this.stack.size();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user