package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; 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.FloatInfo; import com.coderising.jvm.constant.IntegerInfo; 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 by = new ByteCodeIterator(codes); ClassFile file = new ClassFile(); String magicNum = by.nextU4HexString(); if(!magicNum.equals("cafebabe")){ throw new RuntimeException("文件类型错误"); } int minVersion = by.nextU2Int(); int majorVersion = by.nextU2Int(); ConstantPool constant = parseConstantPool(by); AccessFlag flag = parseAccessFlag(by); ClassIndex index = parseClassIndex(by); parseInterfaces(by); file.setMinorVersion(minVersion); file.setMajorVersion(majorVersion); file.setAccessFlag(flag); file.setClassIndex(index); file.setConstPool(constant); List<Field> fields = parseField(by,constant); List<Method> methods = parseMethod(by,file); for(Field field:fields){ file.addField(field); } for(Method method:methods){ file.addMethod(method); } return file; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag flag = new AccessFlag(iter.nextU2Int()); return flag; } private ClassIndex parseClassIndex(ByteCodeIterator iter) { ClassIndex index = new ClassIndex(); index.setThisClassIndex(iter.nextU2Int()); index.setSuperClassIndex(iter.nextU2Int()); return index; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantCount = iter.nextU2Int(); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for(int i=1;i<constantCount;i++){ int tag = iter.nextU1Int(); if(tag == 1){ UTF8Info utf8 = new UTF8Info(pool); int length = iter.nextU2Int(); try { utf8.setValue(new String(iter.getByteByLength(length),"utf-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } pool.addConstantInfo(utf8); }else if(tag == 3){ IntegerInfo integer = new IntegerInfo(pool); integer.setValue(iter.nextU4Integer()); pool.addConstantInfo(integer); }else if(tag == 4){ FloatInfo floatInfo = new FloatInfo(pool); floatInfo.setValue(iter.nextU4Float()); pool.addConstantInfo(floatInfo); }else if(tag == 7){ ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(iter.nextU2Int()); pool.addConstantInfo(classInfo); }else if(tag == 8){ StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(iter.nextU2Int()); pool.addConstantInfo(stringInfo); }else if(tag ==9){ FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(iter.nextU2Int()); fieldRefInfo.setNameAndTypeIndex(iter.nextU2Int()); pool.addConstantInfo(fieldRefInfo); }else if(tag == 10){ MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(iter.nextU2Int()); methodRefInfo.setNameAndTypeIndex(iter.nextU2Int()); pool.addConstantInfo(methodRefInfo); }else if(tag == 12){ NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(iter.nextU2Int()); nameAndTypeInfo.setIndex2(iter.nextU2Int()); pool.addConstantInfo(nameAndTypeInfo); } } return pool; } private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextU2Int(); System.out.println("interfaceCount:" + interfaceCount); } private List<Field> parseField(ByteCodeIterator by,ConstantPool pool) { // TODO Auto-generated method stub List<Field> result = new ArrayList<Field>(); int fieldCount = by.nextU2Int(); for(int i=0;i<fieldCount;i++){ Field field = Field.parse(pool, by); result.add(field); } return result; } private List<Method> parseMethod(ByteCodeIterator by,ClassFile file) { // TODO Auto-generated method stub List<Method> result = new ArrayList<Method>(); int methodCount = by.nextU2Int(); for(int i=0;i<methodCount;i++){ Method method = Method.parse(file, by); result.add(method); } return result; } }