package main.coding_170430.jvm.loader; import main.coding_170430.jvm.clz.AccessFlag; import main.coding_170430.jvm.clz.ClassFile; import main.coding_170430.jvm.clz.ClassIndex; import main.coding_170430.jvm.constant.*; import main.coding_170430.jvm.field.Field; import main.coding_170430.jvm.method.Method; import java.io.UnsupportedEncodingException; /** * Created by peter on 2017/4/21. */ public class ClassFileParse { public ClassFile parse(byte[] codes) { ClassFile clzFile = new ClassFile(); ByteCodeIterator iterator = new ByteCodeIterator(codes); String magicNumber = iterator.nextU4ToHexString(); if (!"cafebabe".equals(magicNumber)) { return null; } clzFile.setMinorVersion(iterator.nextU2ToInt()); clzFile.setMajorVersion(iterator.nextU2ToInt()); ConstantPool pool = parseConstantPool(iterator); clzFile.setConstantPool(pool); AccessFlag flag = parseAccessFlag(iterator); clzFile.setAccessFlag(flag); parseInterfaces(iterator); parseFields(clzFile, iterator); parseMethods(clzFile, iterator); return clzFile; } public AccessFlag parseAccessFlag(ByteCodeIterator iterator) { AccessFlag flag = new AccessFlag(iterator.nextU2ToInt()); return flag; } public ClassIndex parseClassIndex(ByteCodeIterator iterator) { int thisClassIndex = iterator.nextU2ToInt(); int superClassIndex = iterator.nextU2ToInt(); ClassIndex clzIndex = new ClassIndex(); clzIndex.setThisClassIndex(thisClassIndex); clzIndex.setSuperClassIndex(superClassIndex); return clzIndex; } public ConstantPool parseConstantPool(ByteCodeIterator iterator) { int constantPoolCount = iterator.nextU2ToInt(); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for (int i = 1; i <= constantPoolCount - 1; i++) { int tag = iterator.nextU1ToInt(); if (tag == 7) { //Class Info int utf8Index = iterator.nextU2ToInt(); ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(utf8Index); pool.addConstantInfo(classInfo); } else if (tag == 1) { //UTF-8 String int len = iterator.nextU2ToInt(); byte[] data = iterator.getBytes(len); String value = null; try { value = new String(data, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setLength(len); utf8Info.setValue(value); pool.addConstantInfo(utf8Info); } else if (tag == 8) { StringInfo info = new StringInfo(pool); info.setIndex(iterator.nextU2ToInt()); pool.addConstantInfo(info); } else if (tag == 9) { FieldRefInfo field = new FieldRefInfo(pool); field.setClassInfoIndex(iterator.nextU2ToInt()); field.setNameAndTypeIndex(iterator.nextU2ToInt()); pool.addConstantInfo(field); } else if (tag == 10) { //MethodRef MethodRefInfo method = new MethodRefInfo(pool); method.setClassInfoIndex(iterator.nextU2ToInt()); method.setNameAndTypeIndex(iterator.nextU2ToInt()); pool.addConstantInfo(method); } else if (tag == 12) { //Name and Type Info NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndexA(iterator.nextU2ToInt()); nameAndTypeInfo.setIndexB(iterator.nextU2ToInt()); pool.addConstantInfo(nameAndTypeInfo); } else { throw new RuntimeException("the constant pool tag " + tag + " has not implemented"); } } System.out.println("Finished reading Constant pool"); return pool; } public void parseInterfaces(ByteCodeIterator iterator) { int interfaxrCount = iterator.nextU2ToInt(); System.out.println("interfaceCount:" + interfaxrCount); //如果实现了接口这里需要实现 } public void parseFields(ClassFile clzFile, ByteCodeIterator iterator) { int fieldCount = iterator.nextU2ToInt(); for (int i = 1; i <= fieldCount; i++) { Field f = Field.parse(clzFile.getConstantPool(), iterator); clzFile.addField(f); } } public void parseMethods(ClassFile clzfFile, ByteCodeIterator iterator) { int methodCount = iterator.nextU2ToInt(); for (int i = 0; i <= methodCount; i++) { Method m = Method.parse(clzfFile, iterator); clzfFile.addMethod(m); } } }