support Exception

This commit is contained in:
wangxiang
2023-07-25 16:00:02 +08:00
parent 86c3689b1d
commit 1bc96be6cc
7 changed files with 56 additions and 25 deletions

View File

@@ -12,10 +12,8 @@ import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.JvmThreadHolder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.Const;
import org.apache.bcel.classfile.*;
import java.util.HashMap;
import java.util.Map;
@@ -94,11 +92,42 @@ public class JavaExecutionEngine {
for (int i = 0; i < frame.getCodeLength(); ) {
Instruction instruction = instructionMap.get(i);
log.debug("{}│ {}", blank, instruction);
instruction.execute(frame);
if (instruction instanceof RETURN || instruction instanceof ARETURN || instruction instanceof DRETURN || instruction instanceof FRETURN || instruction instanceof IRETURN) {
break;
try {
instruction.execute(frame);
if (instruction instanceof RETURN || instruction instanceof ARETURN || instruction instanceof DRETURN || instruction instanceof FRETURN || instruction instanceof IRETURN) {
break;
}
i += instruction.offSet();
} catch (Exception exception) {
Integer handlerPC = null;
CodeException[] exceptionTable = frame.getMethod().getCode().getExceptionTable();
for (CodeException codeException : exceptionTable) {
if (codeException.getStartPC() <= i & i <= codeException.getEndPC()) {
int catchType = codeException.getCatchType();
// 0, if the handler catches any exception, otherwise it points to the exception class which is to be caught.
if (catchType == 0) {
frame.push(new StackValue(Const.T_OBJECT, exception));
handlerPC = codeException.getHandlerPC();
} else {
String exceptionClassName = frame.getConstantPoolUtil().getConstantClassClassName(catchType);
exceptionClassName = Utility.compactClassName(exceptionClassName, false);
Class<?> exceptionClass = Class.forName(exceptionClassName);
if (exceptionClass.isAssignableFrom(exception.getClass())) {
frame.push(new StackValue(Const.T_OBJECT, exception));
handlerPC = codeException.getHandlerPC();
}
}
}
}
if (handlerPC != null) {
i = handlerPC;
} else {
log.debug("{}└──────────────────[{}] No Exception Handler Return!", blank, stackSize);
throw exception;
}
}
i += instruction.offSet();
}
log.debug("{}└──────────────────[{}] {} | {}", blank, stackSize, frame.klass.getClassName(), frame.getMethod());

View File

@@ -30,7 +30,7 @@ public class ANEWARRAY extends Instruction {
ConstantPool constantPool = frame.getConstantPool();
ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil();
ConstantClass constantClass = constantPool.getConstant(constantClassIndex);
String className = constantPoolUtil.getClassName(constantClass);
String className = constantPoolUtil.getConstantClassClassName(constantClass);
Klass klass = Metaspace.getJavaClass(Utility.compactClassName(className));
if (klass == null) {

View File

@@ -2,6 +2,7 @@ package haidnor.jvm.instruction.references;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import lombok.SneakyThrows;
@@ -14,7 +15,8 @@ public class ATHROW extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
StackValue pop = frame.pop();
throw (Exception) pop.getValue();
}
}

View File

@@ -30,7 +30,7 @@ public class INSTANCEOF extends Instruction {
ConstantPool constantPool = frame.getConstantPool();
ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil();
ConstantClass constantClass = constantPool.getConstant(constantClassIndex);
String className = constantPoolUtil.getClassName(constantClass);
String className = constantPoolUtil.getConstantClassClassName(constantClass);
className = Utility.compactClassName(className);
StackValue stackValue = frame.pop();

View File

@@ -29,7 +29,7 @@ public class NEW extends Instruction {
ConstantPool constantPool = frame.getConstantPool();
ConstantPoolUtil constantPoolUtil = frame.getConstantPoolUtil();
ConstantClass constantClass = constantPool.getConstant(constantClassIndex);
String className = constantPoolUtil.getClassName(constantClass);
String className = constantPoolUtil.getConstantClassClassName(constantClass);
if (className.startsWith("java/")) {
frame.push(new StackValue(Const.T_OBJECT, null));

View File

@@ -42,16 +42,16 @@ public class ConstantPoolUtil {
/**
* 获取长类名, 例如 java/lang/String
*/
public String getClassName(final ConstantClass constantClass) {
public String getConstantClassClassName(final ConstantClass constantClass) {
ConstantUtf8 constantUtf8 = cp.getConstant(constantClass.getNameIndex());
return constantUtf8.getBytes();
}
/**
* 获取长类名, 例如 java/lang/String
*/
public String getClassName(int index) {
ConstantClass constantClass = cp.getConstant(index);
return getClassName(constantClass);
public String getConstantClassClassName(int constantClassIndex) {
ConstantClass constantClass = cp.getConstant(constantClassIndex);
return getConstantClassClassName(constantClass);
}

View File

@@ -4,17 +4,17 @@ package haidnor.jvm.test.demo;
public class Demo7 {
public static void main(String[] args) {
String fun = fun();
System.out.println(fun);
}
public static String fun() {
String str = "hello";
try {
return str;
} finally {
System.out.println("zhangsan");
String name = fun();
System.out.println(name);
} catch (Exception exception) {
System.out.println("计算错误");
}
}
public static String fun() {
System.out.println(1 / 0);
return "zhangsan";
}
}