package com.coderising.jvm.loader;
import com.coderising.jvm.clz.AccessFlag;
import com.coderising.jvm.clz.ClassFile;
import com.coderising.jvm.clz.ClassIndex;
import com.coderising.jvm.constant.*;
import com.coderising.jvm.field.Field;
import com.coderising.jvm.method.Method;
import java.io.UnsupportedEncodingException;
public class ClassFileParser {
public ClassFile parse(byte[] codes) {
ClassFile clzFile = new ClassFile();
ByteCodeIterator iterator = new ByteCodeIterator(codes);
String magicNumber = iterator.nextU4HexString();
if (!"cafebabe".equals(magicNumber)) {
return null;
}
clzFile.setMinorVersion(iterator.nextU2Int());
clzFile.setMajorVersion(iterator.nextU2Int());
clzFile.setConstPool(parseConstantPool(iterator));
clzFile.setAccessFlag(parseAccessFlag(iterator));
clzFile.setClassIndex(parseClassIndex(iterator));
parseInterfaces(iterator);
parseFields(clzFile,iterator);
parseMethods(clzFile,iterator);
return clzFile;
}
private AccessFlag parseAccessFlag(ByteCodeIterator iter) {
AccessFlag accessFlag = new AccessFlag(iter.nextU2Int());
return accessFlag;
}
private ClassIndex parseClassIndex(ByteCodeIterator iter) {
ClassIndex classIndex = new ClassIndex();
classIndex.setThisClassIndex(iter.nextU2Int());
classIndex.setSuperClassIndex(iter.nextU2Int());
return classIndex;
}
private ConstantPool parseConstantPool(ByteCodeIterator iter) {
int constantCount = iter.nextU2Int();
ConstantPool pool = new ConstantPool();
//因为常量池索引是#1开始,所以此处常量池的第0位设置成空
pool.addConstantInfo(new NullConstantInfo());
for (int i = 1; i < constantCount; i++) {
int tag = iter.nextU1Int();
if (tag == 7) {
//CONSTANT_Class_info
ClassInfo classInfo = new ClassInfo(pool);
classInfo.setUtf8Index(iter.nextU2Int());
pool.addConstantInfo(classInfo);
} else if (tag == 1) {
//CONSTANT_Utf8_info
UTF8Info utf8Info = new UTF8Info(pool);
int len = iter.nextU2Int();
utf8Info.setLength(len);
byte[] utf8Bytes = iter.getBytes(len);
String utf8Value = null;
try {
utf8Value = new String(utf8Bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
utf8Info.setValue(utf8Value);
pool.addConstantInfo(utf8Info);
} else if (tag == 8) {
//CONSTANT_String_info
StringInfo stringInfo = new StringInfo(pool);
stringInfo.setIndex(iter.nextU2Int());
pool.addConstantInfo(stringInfo);
} else if (tag == 9) {
//CONSTANT_Fieldref_info
FieldRefInfo fieldRefInfo = new FieldRefInfo(pool);
fieldRefInfo.setClassInfoIndex(iter.nextU2Int());
fieldRefInfo.setNameAndTypeIndex(iter.nextU2Int());
pool.addConstantInfo(fieldRefInfo);
} else if (tag == 10) {
//CONSTANT_Methodref_info
MethodRefInfo methodRefInfo = new MethodRefInfo(pool);
methodRefInfo.setClassIndex(iter.nextU2Int());
methodRefInfo.setNameAndTypeIndex(iter.nextU2Int());
pool.addConstantInfo(methodRefInfo);
} else if (tag == 12) {
//CONSTANT_NameAndType_info
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool);
nameAndTypeInfo.setNameIndex(iter.nextU2Int());
nameAndTypeInfo.setDescriptorIndex(iter.nextU2Int());
pool.addConstantInfo(nameAndTypeInfo);
} else {
throw new RuntimeException("constant pool hasn't this tag : " + tag);
}
}
System.out.println("Finished reading Constant pool ");
return pool;
}
private void parseInterfaces(ByteCodeIterator iter) {
int interfaceCount = iter.nextU2Int();
System.out.println("interfaceCount:" + interfaceCount);
// TODO : 如果实现了interface, 这里需要解析
}
private void parseFields(ClassFile clazzFile,ByteCodeIterator iterator){
int fieldCount = iterator.nextU2Int();
for (int i = 0 ;i<fieldCount;i++){
Field field = Field.parse(clazzFile.getConstantPool(),iterator);
clazzFile.addField(field);
}
}
private void parseMethods(ClassFile clazzFile,ByteCodeIterator iterator){
int methodCount = iterator.nextU2Int();
for(int i = 0;i<methodCount;i++){
Method method = Method.parse(clazzFile,iterator);
clazzFile.addMethod(method);
}
}
}