package task6.jvm.loader; import task6.jvm.clz.AccessFlag; import task6.jvm.clz.ClassFile; import task6.jvm.clz.ClassIndex; import task6.jvm.constant.*; import task6.jvm.field.Field; import task6.jvm.method.Method; import java.util.ArrayList; import java.util.List; public class ClassFileParser { private ConstantPool constantPool; public ClassFile parse(byte[] codes) { ClassFile classFile = new ClassFile(); ByteCodeIterator iterator = new ByteCodeIterator(codes); System.out.println(iterator.getMagicNumber()); classFile.setMinorVersion(iterator.next2Bytes()); classFile.setMajorVersion(iterator.next2Bytes()); parseConstantPool(iterator); classFile.setConstPool(constantPool); classFile.setAccessFlag(parseAccessFlag(iterator)); classFile.setClassIndex(parseClassIndex(iterator));//task5 over iterator.next2Bytes(); // interface classFile.setFields(parseFileds(iterator)); classFile.setMethods(parseMethods(classFile, iterator));//task6 over return classFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { return new AccessFlag(iter.next2Bytes()); } private ClassIndex parseClassIndex(ByteCodeIterator iter) { ClassIndex clazIndex = new ClassIndex(); clazIndex.setThisClassIndex(iter.next2Bytes()); clazIndex.setSuperClassIndex(iter.next2Bytes()); return clazIndex; } private void parseConstantPool(ByteCodeIterator iter) { int poolCount = iter.next2Bytes(); ConstantPool pool = new ConstantPool(poolCount); for (int i = 0; i < poolCount; i++) { int tag = iter.nextFlag(); if (tag == ConstantInfo.UTF8_INFO) { //utf-8 int length = iter.next2Bytes(); byte[] bytes = iter.getBytes(length); UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setValue(new String(bytes)); utf8Info.setLength(length); pool.addConstantInfo(utf8Info); } else if (tag == ConstantInfo.STRING_INFO) { StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(iter.next2Bytes()); pool.addConstantInfo(stringInfo); } else if (tag == ConstantInfo.CLASS_INFO) { ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(iter.next2Bytes()); pool.addConstantInfo(classInfo); } else if (tag == ConstantInfo.FIELD_INFO) { FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(iter.next2Bytes()); fieldRefInfo.setNameAndTypeIndex(iter.next2Bytes()); pool.addConstantInfo(fieldRefInfo); } else if (tag == ConstantInfo.METHOD_INFO) { MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(iter.next2Bytes()); methodRefInfo.setNameAndTypeIndex(iter.next2Bytes()); pool.addConstantInfo(methodRefInfo); } else if (tag == ConstantInfo.NAME_AND_TYPE_INFO) { NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(iter.next2Bytes()); nameAndTypeInfo.setIndex2(iter.next2Bytes()); pool.addConstantInfo(nameAndTypeInfo); } } this.constantPool = pool; } private List<Field> parseFileds(ByteCodeIterator iter) { int fieldCount = iter.next2Bytes(); List<Field> fieldList = new ArrayList<>(fieldCount); for (int i = 0; i < fieldCount; i++) { Field f = Field.parse(constantPool, iter); fieldList.add(f); } return fieldList; } private List<Method> parseMethods(ClassFile classFile, ByteCodeIterator iter) { int methodCount = iter.next2Bytes(); List<Method> methodList = new ArrayList<>(methodCount); for (int i = 0; i < methodCount; i++) { Method m = Method.parse(classFile, iter); methodList.add(m); } return methodList; } }