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 clzFile = new ClassFile(); ByteCodeIterator iter = new ByteCodeIterator(codes); String magicNumber = iter.nextU4ToHexString(); if(!"cafebabe".equals(magicNumber)){ return null; } clzFile.setMinorVersion(iter.nextU2toInt()); clzFile.setMajorVersion(iter.nextU2toInt()); ConstantPool pool = parseConstantPool(iter); clzFile.setConstPool(pool); AccessFlag flag = parseAccessFlag(iter); clzFile.setAccessFlag(flag); ClassIndex clzIndex = parseClassInfex(iter); clzFile.setClassIndex(clzIndex); return clzFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { AccessFlag accessFlag = new AccessFlag(iter.nextU2toInt()); return accessFlag; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { int thisClassIndex = iter.nextU2toInt(); int superClassIndex = iter.nextU2toInt(); ClassIndex clzIndex = new ClassIndex(); clzIndex.setThisClassIndex(thisClassIndex); clzIndex.setSuperClassIndex(superClassIndex); return clzIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantPoolCount = iter.nextU2toInt();//常量池中常量的个数 ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for (int i = 1; i < constantPoolCount - 1; i++) { //常量池 int tag = iter.nextU1toInt(); if(7 == tag){ //ClassInfo int utf8Index = iter.nextU2toInt(); //name_index ClassInfo clzInfo = new ClassInfo(pool); clzInfo.setUtf8Index(utf8Index); pool.addConstantInfo(clzInfo); }else if(1 == tag){ //UTF8 String int len = iter.nextU2toInt(); byte[] data = iter.getBytes(len); String value = null; try { value = new String(data, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setLength(len); utf8Info.setValue(value); pool.addConstantInfo(utf8Info); }else if(8 == tag){ StringInfo strInfo = new StringInfo(pool); strInfo.setIndex(iter.nextU2toInt()); pool.addConstantInfo(strInfo); }else if(9 == tag){ FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(iter.nextU2toInt()); fieldRefInfo.setNameAndTypeIndex(iter.nextU2toInt()); pool.addConstantInfo(fieldRefInfo); }else if(10 == tag){ MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(iter.nextU2toInt()); methodRefInfo.setNameAndTypeIndex(iter.nextU2toInt()); pool.addConstantInfo(methodRefInfo); }else if(12 == tag){ NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(iter.nextU2toInt()); nameAndTypeInfo.setIndex2(iter.nextU2toInt()); pool.addConstantInfo(nameAndTypeInfo); }else { throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); } } return pool; } }