package mini_jvm.loader;
import mini_jvm.clz.AccessFlag;
import mini_jvm.clz.ClassFile;
import mini_jvm.clz.ClassIndex;
import mini_jvm.constant.*;
import java.io.UnsupportedEncodingException;
public class ClassFileParser {
public ClassFile parse(byte[] codes) {
ClassFile classFile = new ClassFile();
ByteCodeIterator iter = new ByteCodeIterator(codes);
//1 先解析魔数
String magicNumber = iter.nextU4ToHexString();
if(!magicNumber.equals("cafebabe")){
return null;
}
//2 解析次版本号 主版本号
classFile.setMinorVersion(iter.nextU2ToInt());
classFile.setMajorVersion(iter.nextU2ToInt());
//3 解析常量池
ConstantPool constantPool = parseConstantPool(iter);
classFile.setConstPool(constantPool);
//4 解析访问标志
AccessFlag accessFlag = parseAccessFlag(iter);
classFile.setAccessFlag(accessFlag);
//5 解析类索引,父类索引,接口索引
ClassIndex classIndex = parseClassInfex(iter);
classFile.setClassIndex(classIndex);
return classFile;
}
private AccessFlag parseAccessFlag(ByteCodeIterator iter) {
return new AccessFlag(iter.nextU2ToInt());
}
private ClassIndex parseClassInfex(ByteCodeIterator iter) {
ClassIndex classIndex = new ClassIndex();
classIndex.setThisClassIndex(iter.nextU2ToInt());
classIndex.setSuperClassIndex(iter.nextU2ToInt());
return classIndex;
}
private ConstantPool parseConstantPool(ByteCodeIterator iter) {
//常量池容量计数值,从1开始,不引用任何一个常量池项目就标为0
int countConstant = iter.nextU2ToInt();
ConstantPool constantPool = new ConstantPool();
//先设置第0个常量项
constantPool.addConstantInfo(new NullConstantInfo());
for(int i=1; i<countConstant; i++){
int tag = iter.nextU1toInt();
switch (tag){
case 1 :
//utf-8编码的字符串
UTF8Info utf8Str = new UTF8Info(constantPool);
//解析字符串长度
int length = iter.nextU2ToInt();
utf8Str.setLength(length);
//根据长度解析出字符串
byte[] bytes = iter.getBytes(length);
try {
utf8Str.setValue(new String(bytes,"UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
constantPool.addConstantInfo(utf8Str);
break;
case 7:
//指向全限定名常量项的索引
ClassInfo classInfo = new ClassInfo(constantPool);
int index = iter.nextU2ToInt();
classInfo.setUtf8Index(index);
constantPool.addConstantInfo(classInfo);
break;
case 8:
//指向字符串字面量的索引
StringInfo stringInfo = new StringInfo(constantPool);
stringInfo.setIndex(iter.nextU2ToInt());
constantPool.addConstantInfo(stringInfo);
break;
case 9:
//指向声明字段的类或者接口的Class_info的索引项
FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool);
fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt());
fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt());
constantPool.addConstantInfo(fieldRefInfo);
break;
case 10:
//指向声明方法的类描述符class_info的索引项
MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool);
methodRefInfo.setClassInfoIndex(iter.nextU2ToInt());
methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt());
constantPool.addConstantInfo(methodRefInfo);
break;
case 12:
//指向该字段或方法名称的常量项的索引
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool);
nameAndTypeInfo.setIndex1(iter.nextU2ToInt());
nameAndTypeInfo.setIndex2(iter.nextU2ToInt());
constantPool.addConstantInfo(nameAndTypeInfo);
break;
default:
throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet.");
}
}
return constantPool;
}
}