package jvm.loader;
import java.io.UnsupportedEncodingException;
import jvm.clz.AccessFlag;
import jvm.clz.ClassFile;
import jvm.clz.ClassIndex;
import jvm.constant.ClassInfo;
import jvm.constant.ConstantInfo;
import jvm.constant.ConstantPool;
import jvm.constant.FieldRefInfo;
import jvm.constant.MethodRefInfo;
import jvm.constant.NameAndTypeInfo;
import jvm.constant.NullConstantInfo;
import jvm.constant.StringInfo;
import jvm.constant.UTF8Info;
import jvm.field.Field;
import jvm.method.Method;
public class ClassFileParser {
private ConstantPool constantPool;
public ClassFile parse(byte[] codes) {
ClassFile clzFile = new ClassFile();
ByteCodeIterator iter = new ByteCodeIterator(codes);
iter.nextUxToHexString(4);
clzFile.setMinorVersion(iter.nextU2ToInt());
clzFile.setMajorVersion(iter.nextU2ToInt());
this.constantPool = parseConstantPool(iter);
clzFile.setConstPool(constantPool);
AccessFlag accessFlag = parseAccessFlag(iter);
clzFile.setAccessFlag(accessFlag);
ClassIndex clzIndex = parseClassInfex(iter);
clzFile.setClassIndex(clzIndex);
parseInterfaces(iter);//接口
parseFileds(clzFile, iter);
parseMethods(clzFile, iter);
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 superClassIndex = iter.nextU2ToInt();
classIndex.setThisClassIndex(thisClassIndex);
classIndex.setSuperClassIndex(superClassIndex);
return classIndex;
}
// 常量池
private ConstantPool parseConstantPool(ByteCodeIterator iter) {
ConstantPool constantPool = new ConstantPool();
int poolSize = iter.nextU2ToInt();
constantPool.addConstantInfo(new NullConstantInfo());
for(int i = 1; i < poolSize; i++){
ConstantInfo constantInfo = null;
int type = iter.nextU1toInt();
if(type == 1){
UTF8Info utf8Info = new UTF8Info(constantPool);
int length = iter.nextU2ToInt();
byte[] data = iter.getBytes(length);
String value = null;
try {
value = new String(data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
utf8Info.setLength(length);
utf8Info.setValue(value);
constantInfo = utf8Info;
}else if(type == 7){
ClassInfo classInfo = new ClassInfo(constantPool);
classInfo.setUtf8Index(iter.nextU2ToInt());
constantInfo = classInfo;
}else if(type == 8){
StringInfo stringInfo = new StringInfo(constantPool);
stringInfo.setIndex(iter.nextU2ToInt());
constantInfo = stringInfo;
}else if(type == 9){
FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool);
fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt());
fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt());
constantInfo = fieldRefInfo;
}else if(type == 10){
MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool);
methodRefInfo.setClassInfoIndex(iter.nextU2ToInt());
methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt());
constantInfo = methodRefInfo;
}else if(type == 12){
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool);
nameAndTypeInfo.setIndex1(iter.nextU2ToInt());
nameAndTypeInfo.setIndex2(iter.nextU2ToInt());
constantInfo = nameAndTypeInfo;
}else{
throw new RuntimeException("type: "+type+" 不在范围之内");
}
constantPool.addConstantInfo(constantInfo);
}
return constantPool;
}
private void parseInterfaces(ByteCodeIterator iter) {
int interfaceCount = iter.nextU2ToInt();
// System.out.println("interfaceCount:" + interfaceCount);
// TODO : 如果实现了interface, 这里需要解析
}
private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) {
int fieldCount = iter.nextU2ToInt();
for(int i = 0; i < fieldCount; i++){
Field field = Field.parse(clzFile.getConstantPool(), iter);
clzFile.addField(field);
}
}
private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) {
int methodCount = iter.nextU2ToInt();
for(int i = 0; i < methodCount; i++){
Method method = Method.parse(clzFile, iter);
clzFile.addMethod(method);
}
}
}