package com.github.wdn.coding2017.jvm.loader; import com.github.wdn.coding2017.jvm.clz.*; import com.github.wdn.coding2017.jvm.constant.*; import com.github.wdn.coding2017.jvm.field.Field; import com.github.wdn.coding2017.jvm.method.Method; import java.util.ArrayList; import java.util.List; public class ClassFileParser { ConstantPool pool = new ConstantPool(); public ClassFile parse(byte[] codes) { ByteCodeIterator iter = new ByteCodeIterator(codes); String magic = iter.readU4ToString(); if(!"cafebabe".equals(magic)){ throw new Error(); } ClassFile classFile = new ClassFile(); classFile.setMinorVersion(iter.readU2ToInt()); classFile.setMajorVersion(iter.readU2ToInt()); classFile.setConstantPool(parseConstantPool(iter)); classFile.setAccessFlag(parseAccessFlag(iter)); classFile.setClassIndex(parseClassIndex(iter)); parseInterface(iter); classFile.setFields(parseField(iter)); classFile.setMethods(parseMethod(classFile,iter)); return classFile; } private List<Method> parseMethod(ClassFile classFile,ByteCodeIterator iter) { int methodCount = iter.readU2ToInt(); List<Method> methods = new ArrayList<>(methodCount); for (int i = 0; i < methodCount; i++) { Method method = Method.parse(classFile, iter); method.setPool(pool); methods.add(method); } return methods; } private List<Field> parseField(ByteCodeIterator iter) { int fieldsCount = iter.readU2ToInt(); List<Field> fields = new ArrayList<>(fieldsCount); for (int i = 0; i < fieldsCount; i++) { Field field = Field.parse(iter); field.setPool(pool); fields.add(field); } return fields; } private void parseInterface(ByteCodeIterator iter){ int interfaceNum = iter.readU2ToInt(); if (interfaceNum > 0) { throw new RuntimeException("接口数量>0"); } } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { return new AccessFlag(iter.readU2ToInt()); } private ClassIndex parseClassIndex(ByteCodeIterator iter) { return new ClassIndex(iter.readU2ToInt(),iter.readU2ToInt()); } public ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantPoolNum = iter.readU2ToInt(); for (int i = 0; i < constantPoolNum-1; i++) { int type = iter.readToInt(); if(type==7){// class ClassInfo classInfo = new ClassInfo(pool); classInfo.setNameIndex(iter.readU2ToInt()); pool.put(classInfo); }else if(type==9){// Fieldref FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(iter.readU2ToInt()); fieldRefInfo.setNameAndTypeIndex(iter.readU2ToInt()); pool.put(fieldRefInfo); }else if(type==10){// Methodref MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(iter.readU2ToInt()); methodRefInfo.setNameAndTypeIndex(iter.readU2ToInt()); pool.put(methodRefInfo); }else if(type==1){// Utf8 int length = iter.readU2ToInt(); String value = iter.readCustomToString(length); UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setValue(value); pool.put(utf8Info); }else if(type==8){// String StringInfo stringInfo = new StringInfo(pool); stringInfo.setStringIndex(iter.readU2ToInt()); pool.put(stringInfo); }else if(type==12){// NameAndType NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setNameIndex(iter.readU2ToInt()); nameAndTypeInfo.setDescriptorIndex(iter.readU2ToInt()); pool.put(nameAndTypeInfo); }else{ throw new RuntimeException("未知类型"+type); } } return pool; } }