package com.bruce.homework0409.jvm.loader; import com.bruce.homework0409.jvm.clz.AccessFlag; import com.bruce.homework0409.jvm.clz.ClassFile; import com.bruce.homework0409.jvm.clz.ClassIndex; import com.bruce.homework0409.jvm.constant.ClassInfo; import com.bruce.homework0409.jvm.constant.ConstantPool; import com.bruce.homework0409.jvm.constant.FieldRefInfo; import com.bruce.homework0409.jvm.constant.MethodRefInfo; import com.bruce.homework0409.jvm.constant.NameAndTypeInfo; import com.bruce.homework0409.jvm.constant.NullConstantInfo; import com.bruce.homework0409.jvm.constant.StringInfo; import com.bruce.homework0409.jvm.constant.UTF8Info; import java.util.Arrays; public class ClassFileParser { public ClassFile parse(byte[] codes) { ClassFile clzFile = new ClassFile(); ByteCodeIterator iter = new ByteCodeIterator(codes); String magicNumber = iter.nextU4ToHexString(); if (!"cafebabe".equalsIgnoreCase(magicNumber)) { return null; } clzFile.setMinorVersion(iter.nextU2ToInt()); clzFile.setMajorVersion(iter.nextU2ToInt()); ConstantPool pool = parseConstantPool(iter); clzFile.setConstPool(pool); AccessFlag flag = parseAccessFlag(iter); clzFile.setAccessFlag(flag); ClassIndex index = parseClassInfex(iter); clzFile.setClassIndex(index); return clzFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { int flagValue = iter.nextU1ToInt(); AccessFlag flag = new AccessFlag(flagValue); return flag; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { ClassIndex clzIndex = new ClassIndex(); int thisClassIndex = iter.nextU2ToInt(); int superClassIndex = iter.nextU2ToInt(); clzIndex.setThisClassIndex(thisClassIndex); clzIndex.setSuperClassIndex(superClassIndex); return clzIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantPoolCount = iter.nextU2ToInt(); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for (int i = 1; i < constantPoolCount - 1; i++) { int tag = iter.nextU1ToInt(); if (tag == 7) {//class_info int utf8Index = iter.nextU2ToInt(); ClassInfo clzInfo = new ClassInfo(pool); clzInfo.setUtf8Index(utf8Index); pool.addConstantInfo(clzInfo); } else if (tag == 1) {//utf8_info int len = iter.nextU2ToInt(); byte[] data = iter.getBytes(len); UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setValue(Arrays.toString(data)); pool.addConstantInfo(utf8Info); } else if (tag == 9) {//fieldref_info int clzIndex = iter.nextU2ToInt(); int nameAndTypeIndex = iter.nextU2ToInt(); FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(clzIndex); fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); pool.addConstantInfo(fieldRefInfo); } else if (tag == 10) {//methodref_info int clzIndex = iter.nextU2ToInt(); int nameAndTypeIndex = iter.nextU2ToInt(); MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(clzIndex); methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); pool.addConstantInfo(methodRefInfo); } else if (tag == 12) {//nameAndType_info int nameIndex = iter.nextU2ToInt(); int descriptorIndex = iter.nextU2ToInt(); NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(nameIndex); nameAndTypeInfo.setIndex2(descriptorIndex); pool.addConstantInfo(nameAndTypeInfo); } else if (tag == 8) {//string_info int stringIndex = iter.nextU2ToInt(); StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(stringIndex); pool.addConstantInfo(stringInfo); } else { throw new RuntimeException("The constant "+ tag + " has not been build"); } } return null; } }