package com.github.ipk2015.coding2017.minijvm.loader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.github.ipk2015.coding2017.minijvm.clz.AccessFlag; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.clz.ClassIndex; import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; import com.github.ipk2015.coding2017.minijvm.constant.FieldRefInfo; import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; import com.github.ipk2015.coding2017.minijvm.constant.NameAndTypeInfo; import com.github.ipk2015.coding2017.minijvm.constant.NullConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.StringInfo; import com.github.ipk2015.coding2017.minijvm.constant.UTF8Info; import com.github.ipk2015.coding2017.minijvm.field.Field; import com.github.ipk2015.coding2017.minijvm.method.Method; import com.github.ipk2015.coding2017.minijvm.util.Util; public class ClassFileParser { public ClassFile parse(byte[] codes) { ClassFile classFile = new ClassFile(); ByteCodeIterator iterator = new ByteCodeIterator(codes); String magicNum = iterator.nextUNToHexString(4); if(!"cafebabe".equalsIgnoreCase(magicNum)){ return null; } classFile.setMinorVersion(iterator.nextUNToInt(2)); classFile.setMajorVersion(iterator.nextUNToInt(2)); ConstantPool constantPool = parseConstantPool(iterator); classFile.setConstPool(constantPool); AccessFlag accessFlag = parseAccessFlag(iterator); classFile.setAccessFlag(accessFlag); ClassIndex classIndex = parseClassInfex(iterator); classFile.setClassIndex(classIndex); parseInterfaces(iterator); List<Field> parseFields = parseFields(constantPool,iterator); for(Field f:parseFields){ classFile.addField(f); } List<Method> parseMethods = parseMethods(classFile,iterator); for(Method m:parseMethods){ classFile.addMethod(m); } return classFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag flag = new AccessFlag(iter.nextUNToInt(2)); return flag; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { ClassIndex classIndex = new ClassIndex(); classIndex.setThisClassIndex(iter.nextUNToInt(2)); classIndex.setSuperClassIndex(iter.nextUNToInt(2)); return classIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { int poolSize = iter.nextUNToInt(2); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); int tag; for(int i = 1;i < poolSize; i++){ tag = iter.nextUNToInt(1); switch(tag){ case ConstantInfo.CLASS_INFO: meetClassInfo(pool,iter); break; case ConstantInfo.FIELD_INFO: meetFieldInfo(pool,iter); break; case ConstantInfo.METHOD_INFO: meetMethodInfo(pool,iter); break; case ConstantInfo.NAME_AND_TYPE_INFO: meetNameAndTypeInfo(pool,iter); break; case ConstantInfo.STRING_INFO: meetStringInfo(pool,iter); break; case ConstantInfo.UTF8_INFO: meetUTF8Info(pool,iter); break; default: throw new RuntimeException("还没有关于此的处理,tag:"+tag); } } return pool; } private void meetClassInfo(ConstantPool pool,ByteCodeIterator iter){ ClassInfo info = new ClassInfo(pool); info.setUtf8Index(iter.nextUNToInt(2)); pool.addConstantInfo(info); } private void meetFieldInfo(ConstantPool pool,ByteCodeIterator iter){ FieldRefInfo info = new FieldRefInfo(pool); info.setClassInfoIndex(iter.nextUNToInt(2)); info.setNameAndTypeIndex(iter.nextUNToInt(2)); pool.addConstantInfo(info); } private void meetMethodInfo(ConstantPool pool,ByteCodeIterator iter){ MethodRefInfo info = new MethodRefInfo(pool); info.setClassInfoIndex(iter.nextUNToInt(2)); info.setNameAndTypeIndex(iter.nextUNToInt(2)); pool.addConstantInfo(info); } private void meetNameAndTypeInfo(ConstantPool pool,ByteCodeIterator iter){ NameAndTypeInfo info = new NameAndTypeInfo(pool); info.setIndex1(iter.nextUNToInt(2)); info.setIndex2(iter.nextUNToInt(2)); pool.addConstantInfo(info); } private void meetStringInfo(ConstantPool pool,ByteCodeIterator iter){ StringInfo info = new StringInfo(pool); info.setIndex(iter.nextUNToInt(2)); pool.addConstantInfo(info); } private void meetUTF8Info(ConstantPool pool,ByteCodeIterator iter){ int length = iter.nextUNToInt(2); byte[] data = iter.nextUNToArray(length); String value = null; try { value=new String(data,"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } UTF8Info info = new UTF8Info(pool); info.setLength(length); info.setValue(value); pool.addConstantInfo(info); } private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextUNToInt(2); // System.out.println("interfaceCount:" + interfaceCount); // TODO : 如果实现了interface, 这里需要解析 } private List<Field> parseFields(ConstantPool pool,ByteCodeIterator iter){ List<Field> list = new ArrayList(); int count = iter.nextUNToInt(2); for(int i = 0;i < count;i++){ list.add(Field.parse(pool, iter)); } return list; } private List<Method> parseMethods(ClassFile classFile,ByteCodeIterator iter){ List<Method> list = new ArrayList(); int count = iter.nextUNToInt(2); for(int i = 0;i < count;i++){ list.add(Method.parse(classFile, iter)); } return list; } }