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 sun.invoke.util.BytecodeDescriptor; import javax.lang.model.element.Name; 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()); clzFile.setConstPool(parseConstantPool(iter)); clzFile.setAccessFlag(parseAccessFlag(iter)); clzFile.setClassIndex(parseClassInfex(iter)); return clzFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { return new AccessFlag(iter.nextU2ToInt()); } private ClassIndex parseClassInfex(ByteCodeIterator iter) { ClassIndex clzIndex = new ClassIndex(); clzIndex.setThisClassIndex(iter.nextU2ToInt()); clzIndex.setSuperClassIndex(iter.nextU2ToInt()); return clzIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { int constantNum = iter.nextU2ToInt(); ConstantPool pool = new ConstantPool(); pool.addConstantInfo(new NullConstantInfo()); for (int i = 0; i < constantNum - 1; i++) { int tag = iter.nextU1ToInt(); if (tag == 1) { //utf-8_info int len = iter.nextU2ToInt(); byte[] buffer = new byte[len]; buffer = iter.getCodes(len); String s = null; try { s = new String(buffer, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } UTF8Info utf8Info = new UTF8Info(pool); utf8Info.setLength(len); utf8Info.setValue(s); pool.addConstantInfo(utf8Info); } else if (tag == 7) { //class_info int utf8Index = iter.nextU2ToInt(); ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(utf8Index); pool.addConstantInfo(classInfo); } else if (tag == 8) { int stringIndex = iter.nextU2ToInt(); StringInfo stringInfo = new StringInfo(pool); stringInfo.setIndex(stringIndex); pool.addConstantInfo(stringInfo); } else if (tag == 9) { FieldRefInfo info = new FieldRefInfo(pool); info.setClassInfoIndex(iter.nextU2ToInt()); info.setNameAndTypeIndex(iter.nextU2ToInt()); pool.addConstantInfo(info); } else if (tag == 10) { MethodRefInfo info = new MethodRefInfo(pool); info.setClassInfoIndex(iter.nextU2ToInt()); info.setNameAndTypeIndex(iter.nextU2ToInt()); pool.addConstantInfo(info); } else if (tag == 12) { NameAndTypeInfo info = new NameAndTypeInfo(pool); info.setIndex1((iter.nextU2ToInt())); info.setIndex2(iter.nextU2ToInt()); pool.addConstantInfo(info); } else { throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); } } return pool; } }