package com.coding.basic.homework_04.jvm.clz; import java.io.UnsupportedEncodingException; import com.coding.basic.homework_04.jvm.attr.AccessFlag; import com.coding.basic.homework_04.jvm.constant.ConstantPool; import com.coding.basic.homework_04.jvm.field.Field; import com.coding.basic.homework_04.jvm.info.ClassInfo; import com.coding.basic.homework_04.jvm.info.FieldRefInfo; import com.coding.basic.homework_04.jvm.info.MethodRefInfo; import com.coding.basic.homework_04.jvm.info.NameAndTypeInfo; import com.coding.basic.homework_04.jvm.info.NullConstantInfo; import com.coding.basic.homework_04.jvm.info.StringInfo; import com.coding.basic.homework_04.jvm.info.UTF8Info; import com.coding.basic.homework_04.jvm.method.Method; import com.coding.basic.homework_04.jvm.util.ByteCodeIterator; public class ClassFileParser { private ClassFile clzFile; private ConstantPool pool; public ClassFile parser(byte[] codes) { ByteCodeIterator iterator = new ByteCodeIterator(codes); clzFile = new ClassFile(); clzFile.setMagicNumber(iterator.nextU4ToHexString()); clzFile.setMinorVersion(iterator.nextU2ToInt()); clzFile.setMajorVersion(iterator.nextU2ToInt()); clzFile.setConstantNum(iterator.nextU2ToInt()); clzFile.setConstantPool(parserConstantPool(iterator)); clzFile.setAccessFlag(new AccessFlag(iterator.nextU2ToInt())); parseClzIndex(clzFile, iterator); parseInterface(iterator); parseField(clzFile, iterator); parseMethod(clzFile, iterator); return clzFile; } private void parseClzIndex(ClassFile clzFile, ByteCodeIterator iterator) { ClassIndex clzIndex = new ClassIndex(); clzIndex.setThisClassIndex(iterator.nextU2ToInt()); clzIndex.setSuperClassIndex(iterator.nextU2ToInt()); clzFile.setClzIndex(clzIndex); } private void parseMethod(ClassFile clzFile, ByteCodeIterator iterator) { int methodCount = iterator.nextU2ToInt(); for(int i=0; i<methodCount; i++){ Method method = Method.parse(clzFile, iterator); clzFile.addMethod(method); } } private void parseField(ClassFile clzFile, ByteCodeIterator iterator) { int fieldCount = iterator.nextU2ToInt(); for(int i=0; i<fieldCount; i++){ Field field = Field.parse(clzFile.getConstantPool(), iterator); clzFile.addField(field); } } private void parseInterface(ByteCodeIterator iterator) { int count = iterator.nextU2ToInt(); //TODO 如果类中有接口,这里需要解析 } private ConstantPool parserConstantPool(ByteCodeIterator iterator){ pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for(int i=1; i <= clzFile.getConstantNum() - 1; i++){ int tag = iterator.nextU1toInt(); if(tag == 7){ //class info ClassInfo clzInfo = new ClassInfo(pool); clzInfo.setUtf8Index(iterator.nextU2ToInt()); pool.addConstantInfo(clzInfo); }else if(tag == 1){ //utf8 info 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 utf8Str = new UTF8Info(pool); utf8Str.setLength(len); utf8Str.setValue(value); pool.addConstantInfo(utf8Str); }else if(tag == 8){ //String info StringInfo stringInfo = new StringInfo(pool); stringInfo.setString_index(iterator.nextU2ToInt()); pool.addConstantInfo(stringInfo); }else if(tag == 9){ //FieldRef info FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClz_index(iterator.nextU2ToInt()); fieldRefInfo.setNameAndType_index(iterator.nextU2ToInt()); pool.addConstantInfo(fieldRefInfo); }else if(tag == 10){ //MethodRef info MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClass_index(iterator.nextU2ToInt()); methodRefInfo.setNameAndType_index(iterator.nextU2ToInt()); pool.addConstantInfo(methodRefInfo); }else if(tag == 12){ //NameAndType info NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(iterator.nextU2ToInt()); nameAndTypeInfo.setIndex2(iterator.nextU2ToInt()); pool.addConstantInfo(nameAndTypeInfo); }else{ throw new RuntimeException("this tag" + tag+"has no already implement yet!!"); } } System.out.println("finished parser constantPool!!"); return pool; } }