package com.coderising.jvm.loader; 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.ConstantInfo; 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; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; public class ClassFileParser { public ClassFile parse(byte[] codes) { ByteCodeIterator iter = new ByteCodeIterator(codes); ClassFile clzFile = new ClassFile(); String magicNum = iter.getBytesAsHexString(4); if(!"cafebabe".equals(magicNum)){ throw new RuntimeException("Magic Number validation failure, this may not be a java class file."); } int minVer = iter.nextU2AsInt(); int majVer = iter.nextU2AsInt(); System.out.println("magicNum="+magicNum+",minVer="+minVer+",majVer="+majVer); clzFile.setMajorVersion(majVer); clzFile.setMinorVersion(minVer); ConstantPool pool = parseConstantPool(iter); clzFile.setConstPool(pool); AccessFlag accFlag = parseAccessFlag(iter); clzFile.setAccessFlag(accFlag); ClassIndex clsIdx = parseClassIndex(iter); clzFile.setClassIndex(clsIdx); parseInterfaces(iter,pool,clzFile); parseFields(iter, pool, clzFile); parseMethods(iter, pool, clzFile); return clzFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag af = new AccessFlag(iter.nextU2AsInt()); return af; } private ClassIndex parseClassIndex(ByteCodeIterator iter) { ClassIndex ci = new ClassIndex(); ci.setThisClassIndex(iter.nextU2AsInt()); ci.setSuperClassIndex(iter.nextU2AsInt()); return ci; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { ConstantPool cp = new ConstantPool(); cp.addConstantInfo(new NullConstantInfo()); int cpLen = iter.nextU2AsInt(); for(int i=0;i<cpLen-1;i++){ int typeFlag = iter.nextU1AsInt(); switch(typeFlag){ case ConstantInfo.CLASS_INFO: //class info ClassInfo cf = new ClassInfo(cp); cf.setUtf8Index(iter.nextU2AsInt()); cp.addConstantInfo(cf); break; case ConstantInfo.UTF8_INFO: //UTF8 info UTF8Info ui = new UTF8Info(cp); ui.setLength(iter.nextU2AsInt()); ui.setValue(iter.getBytesAsString(ui.getLength())); cp.addConstantInfo(ui); break; case ConstantInfo.STRING_INFO: StringInfo ci = new StringInfo(cp); ci.setIndex(iter.nextU2AsInt()); cp.addConstantInfo(ci); break; case ConstantInfo.FIELD_INFO: FieldRefInfo fri = new FieldRefInfo(cp); fri.setClassInfoIndex(iter.nextU2AsInt()); fri.setNameAndTypeIndex(iter.nextU2AsInt()); cp.addConstantInfo(fri); break; case ConstantInfo.METHOD_INFO: MethodRefInfo mri = new MethodRefInfo(cp); mri.setClassInfoIndex(iter.nextU2AsInt()); mri.setNameAndTypeIndex(iter.nextU2AsInt()); cp.addConstantInfo(mri); break; case ConstantInfo.NAME_AND_TYPE_INFO: NameAndTypeInfo nti = new NameAndTypeInfo(cp); nti.setIndex1(iter.nextU2AsInt()); nti.setIndex2(iter.nextU2AsInt()); cp.addConstantInfo(nti); break; default : throw new RuntimeException("Parse exception:"+typeFlag); } } return cp; } private void parseInterfaces(ByteCodeIterator iter, ConstantPool pool, ClassFile clz){ int interfaceCount = iter.nextU2AsInt(); System.out.println("Total number of interface="+interfaceCount); for(int i=0;i<interfaceCount;i++){ System.out.println("Parse Interface="+iter.nextU2AsInt()); } } private void parseFields(ByteCodeIterator iter, ConstantPool pool, ClassFile clz){ int fieldCount = iter.nextU2AsInt(); System.out.println("Total number of fields="+fieldCount); for(int i=0;i<fieldCount;i++){ Field field = Field.parse(pool, iter); clz.addField(field); } } private void parseMethods(ByteCodeIterator iter, ConstantPool pool, ClassFile clz){ int methodCount = iter.nextU2AsInt(); System.out.println("Total number of methods="+methodCount); for(int i=0;i<methodCount;i++){ Method method = Method.parse(clz,pool, iter); clz.addMethod(method); } } }