This commit is contained in:
wangxiang
2023-10-25 18:06:58 +08:00
parent 74b0140f85
commit 313570d2c2
16 changed files with 138 additions and 260 deletions

View File

@@ -117,4 +117,13 @@ public final class ConstantClass extends Constant implements ConstantObject {
public String toString() {
return super.toString() + "(nameIndex = " + nameIndex + ")";
}
/**
* 获取长类名, 例如 java/lang/String
*/
public String getClassName() {
ConstantUtf8 constantUtf8 = constantPool.getConstant(getNameIndex());
return constantUtf8.getBytes();
}
}

View File

@@ -63,4 +63,29 @@ public final class ConstantFieldref extends ConstantCP {
public void accept(final Visitor v) {
v.visitConstantFieldref(this);
}
/**
* 获取字段所处于Java类的类名, 例如 java/lang/String
*/
public String getBelongClassName() {
ConstantClass constClass = constantPool.getConstant(getClassIndex());
return (String) constClass.getConstantValue(constantPool);
}
/**
* 获取字段名称
*/
public String getName() {
ConstantNameAndType constNameAndType = constantPool.getConstant(getNameAndTypeIndex());
return constNameAndType.getName(constantPool);
}
/**
* 获取字段类型签名
*/
public String getSignature() {
ConstantNameAndType constNameAndType = constantPool.getConstant(getNameAndTypeIndex());
return constNameAndType.getSignature(constantPool);
}
}

View File

@@ -17,6 +17,7 @@
package haidnor.jvm.bcel.classfile;
import haidnor.jvm.bcel.Const;
import lombok.SneakyThrows;
import java.io.DataInput;
import java.io.IOException;
@@ -63,4 +64,49 @@ public final class ConstantInterfaceMethodref extends ConstantCP {
public void accept(final Visitor v) {
v.visitConstantInterfaceMethodref(this);
}
public String getClassName() {
ConstantClass constClass = constantPool.getConstant(getClassIndex());
return (String) constClass.getConstantValue(constantPool);
}
public String getMethodName() {
ConstantNameAndType constNameAndType = constantPool.getConstant(getNameAndTypeIndex());
return constNameAndType.getName(constantPool);
}
public String getMethodSignature() {
ConstantNameAndType constNameAndType = constantPool.getConstant(getNameAndTypeIndex());
return constNameAndType.getSignature(constantPool);
}
public String getReturnType() {
return Utility.methodSignatureReturnType(getMethodSignature(), false);
}
/**
* 解析方法签名返回方法参数类型数组
*/
@SneakyThrows
public Class<?>[] getParameterTypeArr() {
String[] argumentTypeArr = Utility.methodSignatureArgumentTypes(getMethodSignature(), false);
Class<?>[] argumentClassArr = new Class[argumentTypeArr.length];
for (int i = 0; i < argumentTypeArr.length; i++) {
Class<?> argumentClass;
String argumentType = argumentTypeArr[i];
argumentClass = switch (argumentType) {
case "byte" -> byte.class;
case "short" -> short.class;
case "boolean" -> boolean.class;
case "char" -> char.class;
case "int" -> int.class;
case "long" -> long.class;
case "float" -> float.class;
case "double" -> double.class;
default -> Class.forName(argumentType);
};
argumentClassArr[i] = argumentClass;
}
return argumentClassArr;
}
}

View File

@@ -434,163 +434,4 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
return buf.toString();
}
// ---------------------------------------------- haidnorJVM
public ConstantFieldref getConstantFieldref(int constantFieldrefIndex) {
return getConstant(constantFieldrefIndex);
}
public ConstantMethodref getConstantMethodref(int constantMethodrefIndex) {
return getConstant(constantMethodrefIndex);
}
public ConstantClass getConstantClass(int constantClassIndex) {
return getConstant(constantClassIndex);
}
public ConstantNameAndType getConstantNameAndType(int constantNameAndTypeIndex) {
return getConstant(constantNameAndTypeIndex);
}
// ConstantClass ---------------------------------------------------------------------------------------------------
/**
* 获取长类名, 例如 java/lang/String
*/
public String constantClass_ClassName(final ConstantClass constantClass) {
ConstantUtf8 constantUtf8 = getConstant(constantClass.getNameIndex());
return constantUtf8.getBytes();
}
/**
* 获取长类名, 例如 java/lang/String
*/
public String constantClass_ClassName(int constantClassIndex) {
ConstantClass constantClass = getConstant(constantClassIndex);
return constantClass_ClassName(constantClass);
}
// ConstantFieldref ------------------------------------------------------------------------------------------------
/**
* 获取字段所处于Java类的类名, 例如 java/lang/String
*/
public String constantFieldref_ClassName(final ConstantFieldref constantFieldref) {
ConstantClass constClass = getConstant(constantFieldref.getClassIndex());
return (String) constClass.getConstantValue(this);
}
/**
* 获取字段所处于Java类的类名, 例如 java/lang/String
*/
public String constantFieldref_ClassName(int constantFieldrefIndex) {
ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex);
return constantFieldref_ClassName(constantFieldref);
}
/**
* 获取字段名称
*/
public String getFieldName(final ConstantFieldref constantFieldref) {
ConstantNameAndType constNameAndType = getConstant(constantFieldref.getNameAndTypeIndex());
return constNameAndType.getName(this);
}
/**
* 获取字段名称
*/
public String getFieldName(int constantFieldrefIndex) {
ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex);
return getFieldName(constantFieldref);
}
/**
* 获取字段类型签名
*/
public String getFieldSignature(final ConstantFieldref constantFieldref) {
ConstantNameAndType constNameAndType = getConstant(constantFieldref.getNameAndTypeIndex());
return constNameAndType.getSignature(this);
}
/**
* 获取字段类型签名
*/
public String getFieldSignature(int constantFieldrefIndex) {
ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex);
return getFieldSignature(constantFieldref);
}
// ConstantMethodref -----------------------------------------------------------------------------------------------
/**
* 获取方法所处于Java类的类名
* 名称使用/分割,例如 haidnor/jvm/test/instruction/references/NEW
*/
public String constantMethodref_ClassName(final ConstantMethodref methodref) {
ConstantClass constClass = getConstant(methodref.getClassIndex());
return (String) constClass.getConstantValue(this);
}
/**
* 获取方法名
*/
public String constantMethodref_MethodName(final ConstantMethodref methodref) {
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
return constNameAndType.getName(this);
}
/**
* 获取方法签名
*/
public String constantMethodref_MethodSignature(final ConstantMethodref methodref) {
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
return constNameAndType.getSignature(this);
}
// ConstantInterfaceMethodref -----------------------------------------------------------------------------------------------
public String constantInterfaceMethodref_ClassName(final ConstantInterfaceMethodref methodref) {
ConstantClass constClass = getConstant(methodref.getClassIndex());
return (String) constClass.getConstantValue(this);
}
/**
* 获取方法名
*/
public String constantInterfaceMethodref_MethodName(final ConstantInterfaceMethodref methodref) {
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
return constNameAndType.getName(this);
}
/**
* 获取方法签名
*/
public String constantInterfaceMethodref_MethodSignature(final ConstantInterfaceMethodref methodref) {
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
return constNameAndType.getSignature(this);
}
// ConstantNameAndType -----------------------------------------------------------------------------------------------
/**
* ConstantNameAndType
*/
public ConstantNameAndType constantNameAndType(int constantNameAndTypeIndex) {
return getConstant(constantNameAndTypeIndex);
}
public String constantNameAndType_name(int constantNameAndTypeIndex) {
ConstantNameAndType constantNameAndType = constantNameAndType(constantNameAndTypeIndex);
return constantNameAndType.getName(this);
}
public String constantNameAndType_signature(int constantNameAndTypeIndex) {
ConstantNameAndType constantNameAndType = constantNameAndType(constantNameAndTypeIndex);
return constantNameAndType.getSignature(this);
}
}

View File

@@ -121,7 +121,8 @@ public class JavaExecutionEngine {
handlerPC = codeException.getHandlerPC();
} else {
// 从常量池中查询异常表定义的异常类型
String exceptionClassName = frame.getJavaClass().getConstantPool().constantClass_ClassName(catchType);
ConstantClass constantClass = frame.getJavaMethod().getConstantPool().getConstant(catchType);
String exceptionClassName = constantClass.getClassName();
exceptionClassName = Utility.compactClassName(exceptionClassName, false);
// 判断异常的泛型类型. 假如执行指令抛出的是 NullPointerException 类型, 异常表定义的是 Exception 类型, 则此异常可以被捕获

View File

@@ -1,6 +1,7 @@
package haidnor.jvm.instruction.references;
import haidnor.jvm.bcel.Const;
import haidnor.jvm.bcel.classfile.ConstantClass;
import haidnor.jvm.bcel.classfile.JavaClass;
import haidnor.jvm.bcel.classfile.Utility;
import haidnor.jvm.instruction.Instruction;
@@ -10,7 +11,6 @@ import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import lombok.SneakyThrows;
public class ANEWARRAY extends Instruction {
@@ -22,18 +22,18 @@ public class ANEWARRAY extends Instruction {
}
@Override
@SneakyThrows
public void execute(Frame frame) {
String className = frame.getJavaMethod().getConstantPool().constantClass_ClassName(constantClassIndex);
ConstantClass constantClass = frame.getJavaMethod().getConstantPool().getConstant(constantClassIndex);
String className = constantClass.getClassName();
JavaClass klass = Metaspace.getJavaClass(Utility.compactClassName(className));
if (klass == null) {
JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className));
if (javaClass == null) {
// 如果在元空间中找不到已加载的类,则开始进行类加载流程
klass = frame.getJavaClass().getJVMClassLoader().loadWithClassPath(className);
javaClass = frame.getJavaClass().getJVMClassLoader().loadWithClassPath(className);
}
int size = frame.popInt();
Instance[] items = new Instance[size];
InstanceArray instanceArray = new InstanceArray(klass, items);
InstanceArray instanceArray = new InstanceArray(javaClass, items);
frame.push(new StackValue(Const.T_OBJECT, instanceArray));
}

View File

@@ -1,6 +1,6 @@
package haidnor.jvm.instruction.references;
import haidnor.jvm.bcel.classfile.ConstantPool;
import haidnor.jvm.bcel.classfile.ConstantFieldref;
import haidnor.jvm.bcel.classfile.JavaField;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.Instance;
@@ -20,9 +20,9 @@ public class GETFIELD extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
String filedName = constantPool.getFieldName(constantFieldrefIndex);
String fieldSignature = constantPool.getFieldSignature(constantFieldrefIndex);
ConstantFieldref fieldref = frame.getJavaMethod().getConstantPool().getConstant(constantFieldrefIndex);
String filedName = fieldref.getName();
String fieldSignature = fieldref.getSignature();
Instance instanceRef = frame.popRef();
JavaField field = instanceRef.getField(filedName, fieldSignature);

View File

@@ -28,14 +28,13 @@ public class GETSTATIC extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
ConstantFieldref constFieldref = constantPool.getConstant(constantFieldrefIndex);
ConstantFieldref fieldref = frame.getJavaMethod().getConstantPool().getConstant(constantFieldrefIndex);
// 动态链接. 找到字段所属的 Java 类
String className = constantPool.constantFieldref_ClassName(constFieldref);
String className = fieldref.getBelongClassName();
// 动态链接. 找到字段的名字
String fieldName = constantPool.getFieldName(constFieldref);
// 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数.
String fieldName = fieldref.getName();
// 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数.
if (className.startsWith("java/")) {
Class<?> clazz = Class.forName(className.replace('/', '.'));
Field field = clazz.getField(fieldName);

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.references;
import haidnor.jvm.bcel.Const;
import haidnor.jvm.bcel.classfile.ConstantPool;
import haidnor.jvm.bcel.classfile.ConstantClass;
import haidnor.jvm.bcel.classfile.JavaClass;
import haidnor.jvm.bcel.classfile.Utility;
import haidnor.jvm.instruction.Instruction;
@@ -26,9 +26,8 @@ public class INSTANCEOF extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
String className = constantPool.constantClass_ClassName(constantClassIndex);
ConstantClass constantClass = frame.getJavaMethod().getConstantPool().getConstant(constantClassIndex);
String className = constantClass.getClassName();
className = Utility.compactClassName(className);
StackValue stackValue = frame.pop();

View File

@@ -10,7 +10,6 @@ import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.SignatureUtil;
import lombok.SneakyThrows;
import java.lang.reflect.Method;
@@ -35,23 +34,18 @@ public class INVOKEINTERFACE extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
ConstantInterfaceMethodref methodref = frame.getJavaMethod().getConstantPool().getConstant(constantMethodrefIndex);
ConstantInterfaceMethodref interfaceMethodref = constantPool.getConstant(constantMethodrefIndex);
int classIndex = interfaceMethodref.getClassIndex();
String interfaceName = constantPool.constantClass_ClassName(classIndex);
int nameAndTypeIndex = interfaceMethodref.getNameAndTypeIndex();
String methodName = constantPool.constantNameAndType_name(nameAndTypeIndex);
String methodSignature = constantPool.constantNameAndType_signature(nameAndTypeIndex);
String className = methodref.getClassName();
String methodName = methodref.getMethodName();
String methodSignature = methodref.getMethodSignature();
// 系统类反射 自定义类另外处理
if (interfaceName.startsWith("java/")) {
if (className.startsWith("java/")) {
// 解析方法签名得到方法的返回类型
String returnType = Utility.methodSignatureReturnType(methodSignature, false);
String returnType = methodref.getReturnType();
// 执行方法的参数列表
Class<?>[] parameterTypeArr = SignatureUtil.getParameterTypeArr(methodSignature);
Class<?>[] parameterTypeArr = methodref.getParameterTypeArr();
// 执行方法的参数值
Object[] args = frame.popStacksValue(parameterTypeArr.length);
// 将特定的参数转换为基本类型
@@ -78,10 +72,10 @@ public class INVOKEINTERFACE extends Instruction {
}
// 调用自定义类的方法
else {
JavaClass interfaceKlass = Metaspace.getJavaClass(Utility.compactClassName(interfaceName));
if (interfaceKlass == null) {
JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className));
if (javaClass == null) {
JVMClassLoader classLoader = frame.getJavaClass().getJVMClassLoader();
classLoader.loadWithClassPath(interfaceName);
classLoader.loadWithClassPath(className);
}
StackValue stackValue = frame.peek();

View File

@@ -9,7 +9,6 @@ import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.SignatureUtil;
import lombok.SneakyThrows;
/**
@@ -30,9 +29,9 @@ public class INVOKESPECIAL extends Instruction {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
ConstantMethodref methodref = constantPool.getConstant(constantMethodrefIndex);
String className = constantPool.constantMethodref_ClassName(methodref);
String methodName = constantPool.constantMethodref_MethodName(methodref);
String methodSignature = constantPool.constantMethodref_MethodSignature(methodref);
String className = methodref.getClassName();
String methodName = methodref.getMethodName();
String methodSignature = methodref.getMethodSignature();
JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className));
if (javaClass == null) {
@@ -44,7 +43,7 @@ public class INVOKESPECIAL extends Instruction {
// 执行 RT.jar 中 Java 对象构造方法的时候创建java对象
if (methodName.equals("<init>")) {
// 执行方法的参数列表
Class<?>[] parameterTypeArr = SignatureUtil.getParameterTypeArr(methodSignature);
Class<?>[] parameterTypeArr = methodref.getParameterTypeArr();
// 执行方法的参数值
Object[] args = frame.popStacksValue(parameterTypeArr.length);
// 将特定的参数转换为基本类型

View File

@@ -8,7 +8,6 @@ import haidnor.jvm.rtda.Metaspace;
import haidnor.jvm.runtime.Frame;
import haidnor.jvm.runtime.StackValue;
import haidnor.jvm.util.CodeStream;
import haidnor.jvm.util.SignatureUtil;
import lombok.SneakyThrows;
import java.util.Objects;
@@ -33,26 +32,28 @@ public class INVOKESTATIC extends Instruction {
String className;
String methodName;
String methodSignature;
String returnType;
Class<?>[] parameterTypeArr;
Constant constant = constantPool.getConstant(constantIndex);
if (constant instanceof ConstantMethodref constantMethodref) {
className = constantPool.constantMethodref_ClassName(constantMethodref);
methodName = constantPool.constantMethodref_MethodName(constantMethodref);
methodSignature = constantPool.constantMethodref_MethodSignature(constantMethodref);
} else if (constant instanceof ConstantInterfaceMethodref interfaceMethodref) {
className = constantPool.constantInterfaceMethodref_ClassName(interfaceMethodref);
methodName = constantPool.constantInterfaceMethodref_MethodName(interfaceMethodref);
methodSignature = constantPool.constantInterfaceMethodref_MethodSignature(interfaceMethodref);
if (constant instanceof ConstantMethodref methodref) {
className = methodref.getClassName();
methodName = methodref.getMethodName();
methodSignature = methodref.getMethodSignature();
returnType = methodref.getReturnType();
parameterTypeArr = methodref.getParameterTypeArr();
} else if (constant instanceof ConstantInterfaceMethodref methodref) {
className = methodref.getClassName();
methodName = methodref.getMethodName();
methodSignature = methodref.getMethodSignature();
returnType = methodref.getReturnType();
parameterTypeArr = methodref.getParameterTypeArr();
} else {
throw new ClassCastException();
}
// 系统类反射 自定义类另外处理
if (className.startsWith("java/")) {
// 解析方法签名得到方法的返回类型
String returnType = Utility.methodSignatureReturnType(methodSignature, false);
Class<?>[] parameterTypeArr = SignatureUtil.getParameterTypeArr(methodSignature);
Object[] stacksValueArr = frame.popStacksValue(parameterTypeArr.length);
for (int i = 0; i < parameterTypeArr.length; i++) {
Class<?> aClass = parameterTypeArr[i];

View File

@@ -1,7 +1,7 @@
package haidnor.jvm.instruction.references;
import haidnor.jvm.bcel.Const;
import haidnor.jvm.bcel.classfile.ConstantPool;
import haidnor.jvm.bcel.classfile.ConstantClass;
import haidnor.jvm.bcel.classfile.JavaClass;
import haidnor.jvm.bcel.classfile.Utility;
import haidnor.jvm.instruction.Instruction;
@@ -24,8 +24,8 @@ public class NEW extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
String className = constantPool.constantClass_ClassName(constantClassIndex);
ConstantClass constantClass = frame.getJavaMethod().getConstantPool().getConstant(constantClassIndex);
String className = constantClass.getClassName();
if (className.startsWith("java/")) {
frame.push(new StackValue(Const.T_OBJECT, null));

View File

@@ -1,6 +1,6 @@
package haidnor.jvm.instruction.references;
import haidnor.jvm.bcel.classfile.ConstantPool;
import haidnor.jvm.bcel.classfile.ConstantFieldref;
import haidnor.jvm.bcel.classfile.JavaField;
import haidnor.jvm.instruction.Instruction;
import haidnor.jvm.rtda.Instance;
@@ -21,10 +21,9 @@ public class PUTFIELD extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
String filedName = constantPool.getFieldName(constantFieldrefIndex);
String fieldSignature = constantPool.getFieldSignature(constantFieldrefIndex);
ConstantFieldref fieldref = frame.getJavaMethod().getConstantPool().getConstant(constantFieldrefIndex);
String filedName = fieldref.getName();
String fieldSignature = fieldref.getSignature();
StackValue stackValue = frame.pop();

View File

@@ -22,12 +22,11 @@ public class PUTSTATIC extends Instruction {
@Override
@SneakyThrows
public void execute(Frame frame) {
ConstantPool constantPool = frame.getJavaMethod().getConstantPool();
ConstantFieldref constFieldref = constantPool.getConstant(constantFieldrefIndex);
ConstantFieldref constFieldref = frame.getJavaMethod().getConstantPool().getConstant(constantFieldrefIndex);
// 动态链接. 找到字段所属的 Java 类
String className = constantPool.constantFieldref_ClassName(constFieldref);
String className = constFieldref.getBelongClassName();
// 动态链接. 找到字段的名字
String fieldName = constantPool.getFieldName(constFieldref);
String fieldName = constFieldref.getName();
// 以上代码体现了动态链接.Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数.
JavaClass javaClass = Metaspace.getJavaClass(Utility.compactClassName(className));

View File

@@ -1,34 +0,0 @@
package haidnor.jvm.util;
import haidnor.jvm.bcel.classfile.Utility;
import lombok.SneakyThrows;
public abstract class SignatureUtil {
/**
* 解析方法签名返回方法参数类型数组
*/
@SneakyThrows
public static Class<?>[] getParameterTypeArr(String methodeSignature) {
String[] argumentTypeArr = Utility.methodSignatureArgumentTypes(methodeSignature, false);
Class<?>[] argumentClassArr = new Class[argumentTypeArr.length];
for (int i = 0; i < argumentTypeArr.length; i++) {
Class<?> argumentClass;
String argumentType = argumentTypeArr[i];
argumentClass = switch (argumentType) {
case "byte" -> byte.class;
case "short" -> short.class;
case "boolean" -> boolean.class;
case "char" -> char.class;
case "int" -> int.class;
case "long" -> long.class;
case "float" -> float.class;
case "double" -> double.class;
default -> Class.forName(argumentType);
};
argumentClassArr[i] = argumentClass;
}
return argumentClassArr;
}
}