package com.coding.mini_jvm.src.com.coderising.jvm.loader;
import com.coding.mini_jvm.src.com.coderising.jvm.clz.AccessFlag;
import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile;
import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex;
import com.coding.mini_jvm.src.com.coderising.jvm.constant.*;
import com.coding.mini_jvm.src.com.coderising.jvm.field.Field;
import com.coding.mini_jvm.src.com.coderising.jvm.method.Method;
public class ClassFileParser {
public ClassFile parse(byte[] codes) {
ClassFile classFile = new ClassFile();
ByteCodeIterator iterator = new ByteCodeIterator(codes);
//跳过魔数
iterator.skip(4);
//次版本号
classFile.setMinorVersion(iterator.readTwoBytesToInt());
//主版本号
classFile.setMajorVersion(iterator.readTwoBytesToInt());
//解析常量池
ConstantPool constantPool = parseConstantPool(iterator);
classFile.setConstPool(constantPool);
//访问限制符
classFile.setAccessFlag(parseAccessFlag(iterator));
//当前类/父类
classFile.setClassIndex(parseClassIndex(iterator));
//接口数量暂时不实现
int intefaceCount = iterator.readTwoBytesToInt();
if (intefaceCount > 0) {
throw new RuntimeException();
}
//解析字段
parseFields(classFile,iterator, constantPool);
//解析方法
parseMethod(classFile, iterator, constantPool);
return classFile;
}
private AccessFlag parseAccessFlag(ByteCodeIterator iter) {
return new AccessFlag(iter.readTwoBytesToInt());
}
private ClassIndex parseClassIndex(ByteCodeIterator iter) {
ClassIndex classIndex = new ClassIndex();
classIndex.setThisClassIndex(iter.readTwoBytesToInt());
classIndex.setSuperClassIndex(iter.readTwoBytesToInt());
return classIndex;
}
private ConstantPool parseConstantPool(ByteCodeIterator iterator) {
ConstantPool constantPool = new ConstantPool();
//读取常量个数
int constantPoolCount = iterator.readTwoBytesToInt();
constantPool.addConstantInfo(new NullConstantInfo());
for (int i = 1; i < constantPoolCount; i++) {
int flag = iterator.readByteToInt();
int utf8Index;
int clzIndex;
int nameAndTypeIndex;
switch (flag) {
case 1:
int length = iterator.readTwoBytesToInt();
String val = iterator.readBytesToString(length);
UTF8Info utf8Info = new UTF8Info(constantPool);
utf8Info.setLength(length);
utf8Info.setValue(val);
constantPool.addConstantInfo(utf8Info);
break;
case 7:
utf8Index = iterator.readTwoBytesToInt();
ClassInfo classInfo = new ClassInfo(constantPool);
classInfo.setUtf8Index(utf8Index);
constantPool.addConstantInfo(classInfo);
break;
case 8:
utf8Index = iterator.readTwoBytesToInt();
StringInfo stringInfo = new StringInfo(constantPool);
stringInfo.setIndex(utf8Index);
constantPool.addConstantInfo(stringInfo);
break;
case 9:
clzIndex = iterator.readTwoBytesToInt();
nameAndTypeIndex = iterator.readTwoBytesToInt();
FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool);
fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex);
fieldRefInfo.setClassInfoIndex(clzIndex);
constantPool.addConstantInfo(fieldRefInfo);
break;
case 10:
clzIndex = iterator.readTwoBytesToInt();
nameAndTypeIndex = iterator.readTwoBytesToInt();
MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool);
methodRefInfo.setClassInfoIndex(clzIndex);
methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex);
constantPool.addConstantInfo(methodRefInfo);
break;
case 12:
utf8Index = iterator.readTwoBytesToInt();
int utf8Index1 = iterator.readTwoBytesToInt();
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool);
nameAndTypeInfo.setIndex1(utf8Index);
nameAndTypeInfo.setIndex2(utf8Index1);
constantPool.addConstantInfo(nameAndTypeInfo);
break;
default:
throw new RuntimeException("flag "+ flag +" is not exists");
}
}
return constantPool;
}
private void parseFields(ClassFile classFile, ByteCodeIterator iterator, ConstantPool constantPool) {
int fieldCount = iterator.readTwoBytesToInt();
for (int i = 0; i < fieldCount; i++)
classFile.addField(Field.parse(constantPool, iterator));
}
private void parseMethod(ClassFile clzFile, ByteCodeIterator iter, ConstantPool pool) {
int methodCount = iter.readTwoBytesToInt();
for (int i = 0; i < methodCount; i++) {
clzFile.addMethod(Method.parse(clzFile, iter));
}
}
}