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; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; import com.sun.xml.internal.bind.v2.runtime.Name; public class ClassFileParser { public ClassFile parse(byte[] codes) { ClassFile clzFile = new ClassFile(); ByteCodeIterator iter = new ByteCodeIterator(codes); //1.magicNumber String magicNumber = iter.nextU4ToHexString(); if(!magicNumber.equals("cafebabe")){ return null; } //2.Version Number clzFile.setMinorVersion(iter.nextU2ToInt()); clzFile.setMajorVersion(iter.nextU2ToInt()); //3.ConstantPool ConstantPool pool = parseConstantPool(iter); clzFile.setConstPool(pool); //4.AcessFlag AccessFlag flag = parseAccessFlag(iter); clzFile.setAccessFlag(flag); //5.ClassIndex ClassIndex clzIndex = parseClassIndex(iter); clzFile.setClassIndex(clzIndex); //6.Interface parseInterfaces(iter); //7.Filed parseFileds(clzFile, iter); //8.Method parseMethods(clzFile, iter); return clzFile; } /* * --------------------------------------------------------------------------- * 4.Interface * 5.Field * 6.Method */ private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextU2ToInt(); System.out.println("interfaceCount:" + interfaceCount); //TODO:EmployeeV1.java没有实现接口,只读出其接口个数:0;若实现interface,则解析 } private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) { int fieldCount = iter.nextU2ToInt(); System.out.println("fieldCount:" + fieldCount); for(int i = 1; i <= fieldCount; i++){ Field field = Field.parse(clzFile, iter); clzFile.addField(field); } } private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { int methodCount = iter.nextU2ToInt(); System.out.println("methodCount:" + methodCount); for(int i = 1; i <= methodCount; i++){ Method method = Method.parse(clzFile, iter); clzFile.addMethod(method); } } /* * --------------------------------------------------------------------------- * 1.ConstantPool * 2.AccessFlag * 3.ClassIndex */ private ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantpPoolSize = iter.nextU2ToInt(); System.out.println("Constant Pool Size :" + constantpPoolSize); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo());//注意这里 for(int i = 1; i < constantpPoolSize; i++){ int tag = iter.nextU1ToInt(); if(tag == 7) { //ClassInfo int utf8Index = iter.nextU2ToInt(); ClassInfo clzInfo = new ClassInfo(pool); clzInfo.setUtf8Index(utf8Index); pool.addConstantInfo(clzInfo); } else if (tag == 1){ //UTF8Info 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 == 8) { //StringInfo int index = iter.nextU2ToInt(); StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(index); pool.addConstantInfo(stringInfo); } else if (tag == 9) { //FiledRefInfo int classInfoIndex = iter.nextU2ToInt(); int nameAndTypeIndex = iter.nextU2ToInt(); FieldRefInfo field = new FieldRefInfo(pool); field.setClassInfoIndex(classInfoIndex); field.setNameAndTypeIndex(nameAndTypeIndex); pool.addConstantInfo(field); } else if (tag == 10){ //MethodRefInfo int classInfoIndex = iter.nextU2ToInt(); int nameAndTypeIndex = iter.nextU2ToInt(); MethodRefInfo method = new MethodRefInfo(pool); method.setClassInfoIndex(classInfoIndex); method.setNameAndTypeIndex(nameAndTypeIndex); pool.addConstantInfo(method); } else if(tag == 12){ //NameAndTypeInfo int name_index = iter.nextU2ToInt(); int descriptor_index = iter.nextU2ToInt(); NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(name_index); nameAndTypeInfo.setIndex2(descriptor_index); pool.addConstantInfo(nameAndTypeInfo); } else { throw new RuntimeException("the constant pool tag " + tag + "has not been implemented yet"); } } return pool; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); return flag; } private ClassIndex parseClassIndex(ByteCodeIterator iter) { ClassIndex clzIndex = new ClassIndex(); clzIndex.setThisClassIndex(iter.nextU2ToInt()); clzIndex.setSuperClassIndex(iter.nextU2ToInt()); return clzIndex; } }