package com.coderising.jvm.loader; import java.util.ArrayList; import java.util.List; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.MethodRefInfo; import com.coderising.jvm.constant.NameAndTypeInfo; import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; public class ClassFileParser { public ClassFile parse(byte[] codes) { ClassFile classFile = new ClassFile(); ByteCodeIterator iter = new ByteCodeIterator(codes); // String magicNumber = iter.nextUxToHexString(4); iter.nextUxToHexString(4); classFile.setMinorVersion(iter.nextU2ToInt()); classFile.setMajorVersion(iter.nextU2ToInt()); ConstantPool pool = parseConstantPool(iter); classFile.setConstPool(pool); classFile.setAccessFlag(parseAccessFlag(iter)); classFile.setClassIndex(parseClassInfex(iter)); parseInterfaces(iter); classFile.setFields(prarseField(iter, pool)); classFile.setMethods(parseMethod(iter, classFile)); return classFile; } private List<Method> parseMethod(ByteCodeIterator iter, ClassFile classFile) { List<Method> methods = new ArrayList<>(); int mthodsCount = iter.nextU2ToInt(); for(int i=0;i<mthodsCount;i++) { methods.add(Method.parse(classFile, iter)); } return methods; } private List<Field> prarseField(ByteCodeIterator iter, ConstantPool pool) { List<Field> fields = new ArrayList<>(); int fieldsCount = iter.nextU2ToInt(); for(int i=0;i<fieldsCount;i++) { fields.add(Field.parse(pool, iter)); } return fields; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); return accessFlag; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { ClassIndex classIndex = new ClassIndex(); classIndex.setThisClassIndex(iter.nextU2ToInt()); classIndex.setSuperClassIndex(iter.nextU2ToInt()); return classIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); int length = iter.nextU2ToInt(); int type; for(int i=1;i<length;i++){ type = iter.nextU1ToInt(); switch(type){ case 7: ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(iter.nextU2ToInt()); pool.addConstantInfo(classInfo); break; case 1: UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setLength(iter.nextU2ToInt()); utf8Info.setValue(iter.nextUxToString(utf8Info.getLength())); pool.addConstantInfo(utf8Info); break; case 8: StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(iter.nextU2ToInt()); pool.addConstantInfo(stringInfo); break; case 9: FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); pool.addConstantInfo(fieldRefInfo); break; case 10: MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); pool.addConstantInfo(methodRefInfo); break; case 12: NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); pool.addConstantInfo(nameAndTypeInfo); break; default: System.out.println("常量池类型" + type + "还没实现"); break; } } return pool; } private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextU2ToInt(); System.out.println("interfaceCount:" + interfaceCount); // TODO : 如果实现了interface, 这里需要解析 } }