package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.MethodRefInfo; import com.coderising.jvm.constant.NameAndTypeInfo; import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; public class ClassFileParser { public ClassFile parse(byte[] codes) { ClassFile classFile = new ClassFile(); ByteCodeIterator iter = new ByteCodeIterator(codes); String magicNumber = iter.nextU4ToHexString(); if(!magicNumber.equals("cafebabe")){ return null; } classFile.setMinorVersion(iter.nextU2ToInt()); classFile.setMajorVersion(iter.nextU2ToInt()); ConstantPool pool = parseConstantPool(iter); classFile.setConstPool(pool); AccessFlag accessFlag = parseAccessFlag(iter); classFile.setAccessFlag(accessFlag); ClassIndex classIndex = parseClassIndex(iter); classFile.setClassIndex(classIndex); return classFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { int value = iter.nextU2ToInt(); AccessFlag accessFlag = new AccessFlag(value); accessFlag.setFlagValue(value); return accessFlag; } private ClassIndex parseClassIndex(ByteCodeIterator iter) { int thisClassIndex = iter.nextU2ToInt(); int superClassIndex = iter.nextU2ToInt(); ClassIndex classIndex = new ClassIndex(); classIndex.setThisClassIndex(thisClassIndex); classIndex.setSuperClassIndex(superClassIndex); return classIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantPoolCount = iter.nextU2ToInt(); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for (int i = 0; i < constantPoolCount-1; i++) { int tag = iter.nextU1toInt(); if(tag == 7){ int utf8Index = iter.nextU2ToInt(); ClassInfo clzInfo= new ClassInfo(pool); clzInfo.setUtf8Index(utf8Index); pool.addConstantInfo(clzInfo); }else if(tag == 1){ int length = iter.nextU2ToInt(); byte data[] = iter.getBytes(length); String value = null; try { value = new String(data,"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setLength(length); utf8Info.setValue(value); pool.addConstantInfo(utf8Info); }else if(tag == 12){ int NameIndex = iter.nextU2ToInt(); int TypeIndex = iter.nextU2ToInt(); NameAndTypeInfo nameAndType = new NameAndTypeInfo(pool); nameAndType.setIndex1(NameIndex); nameAndType.setIndex2(TypeIndex); pool.addConstantInfo(nameAndType); }else if(tag == 9){ int classInfoIndex = iter.nextU2ToInt(); int nameAndTypeIndex = iter.nextU2ToInt(); FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(classInfoIndex); fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); pool.addConstantInfo(fieldRefInfo); }else if(tag == 10){ int classInfoIndex = iter.nextU2ToInt(); int nameAndTypeIndex = iter.nextU2ToInt(); MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(classInfoIndex); methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); pool.addConstantInfo(methodRefInfo); }else if(tag == 8){ int stringIndex = iter.nextU2ToInt(); StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(stringIndex); pool.addConstantInfo(stringInfo); }else{ throw new RuntimeException("the constant pool tag" + tag + "has not been implemented yet"); } } return pool; } }