package week05.jvm.loader;
import java.io.UnsupportedEncodingException;
import week05.jvm.clz.AccessFlag;
import week05.jvm.clz.ClassFile;
import week05.jvm.clz.ClassIndex;
import week05.jvm.constant.ClassInfo;
import week05.jvm.constant.ConstantPool;
import week05.jvm.constant.FieldRefInfo;
import week05.jvm.constant.MethodRefInfo;
import week05.jvm.constant.NameAndTypeInfo;
import week05.jvm.constant.NullConstantInfo;
import week05.jvm.constant.StringInfo;
import week05.jvm.constant.UTF8Info;
public class ClassFileParser {
public ClassFile parse(byte[] codes) {
ClassFile clzFile = new ClassFile();
ByteCodeIterator iter = new ByteCodeIterator(codes);
String magicNumber = iter.nextU4ToHexString();
if (!"cafebabe".equals(magicNumber)) {
return null;
}
clzFile.setMinorVersion(iter.nextU2ToInt());
clzFile.setMajorVersion(iter.nextU2ToInt());
ConstantPool pool = parseConstantPool(iter);
clzFile.setConstPool(pool);
AccessFlag flag = parseAccessFlag(iter);
clzFile.setAccessFlag(flag);
ClassIndex clzIndex = parseClassInfex(iter);
clzFile.setClassIndex(clzIndex);
return clzFile;
}
private AccessFlag parseAccessFlag(ByteCodeIterator iter) {
int flagValue = iter.nextU2ToInt();
AccessFlag accessFlag = new AccessFlag(flagValue);
return accessFlag;
}
private ClassIndex parseClassInfex(ByteCodeIterator iter) {
ClassIndex classIndex = new ClassIndex();
int thisClassIndex = iter.nextU2ToInt();
int thisSuperIndex = iter.nextU2ToInt();
classIndex.setThisClassIndex(thisClassIndex);
classIndex.setSuperClassIndex(thisSuperIndex);
return classIndex;
}
private ConstantPool parseConstantPool(ByteCodeIterator iter) {
int constPoolCount = iter.nextU2ToInt();
System.out.println("Constant Pool Counts:" + constPoolCount);
ConstantPool pool = new ConstantPool();
pool.addConstantInfo(new NullConstantInfo());
for (int i = 1; i <= constPoolCount - 1; i++) {
int tag = iter.nextU1ToInt();
if (tag == 7) {
// Class Info
int utf8Index = iter.nextU2ToInt();
ClassInfo clzInfo = new ClassInfo(pool);
clzInfo.setUtf8Index(utf8Index);
pool.addConstantInfo(clzInfo);
} else if (tag == 1) {
// UTF-8 String
int len = iter.nextU2ToInt();
byte[] data = iter.getBytes(len);
String value = null;
try {
value = new String(data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
UTF8Info utf8Str = new UTF8Info(pool);
utf8Str.setLength(len);
utf8Str.setValue(value);
pool.addConstantInfo(utf8Str);
} else if (tag == 8) {
//String
StringInfo info = new StringInfo(pool);
info.setIndex(iter.nextU2ToInt());
pool.addConstantInfo(info);
} else if (tag == 9) {
//FieldRef
FieldRefInfo field = new FieldRefInfo(pool);
field.setClassInfoIndex(iter.nextU2ToInt());
field.setNameAndTypeIndex(iter.nextU2ToInt());
pool.addConstantInfo(field);
} else if (tag == 10) {
// MethodRef
MethodRefInfo method = new MethodRefInfo(pool);
method.setClassInfoIndex(iter.nextU2ToInt());
method.setNameAndTypeIndex(iter.nextU2ToInt());
pool.addConstantInfo(method);
} else if (tag == 12) {
// Name and Type Info
NameAndTypeInfo nameType = new NameAndTypeInfo(pool);
nameType.setIndex1(iter.nextU2ToInt());
nameType.setIndex2(iter.nextU2ToInt());
pool.addConstantInfo(nameType);
} else {
throw new RuntimeException("the constant pool tag " + tag + "has not been implemented yet.");
}
}
return pool;
}
}