package com.coderising.jvm.loader; import java.io.UnsupportedEncodingException; 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.cmd.ByteCodeCommand; import com.coderising.jvm.cmd.CommandParser; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantInfo; 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.coderising.jvm.util.Util; public class ClassFileParser { public ClassFile parse(byte[] codes) { ClassFile clf=new ClassFile(); ByteCodeIterator iter=new ByteCodeIterator(codes); String magicNumber=iter.nextU4toString(); if(!"cafebabe".equals(magicNumber)){ return null; } int minorVersion=iter.nextU2toInt(); int majorVersion=iter.nextU2toInt(); clf.setMajorVersion(majorVersion); clf.setMinorVersion(minorVersion); ConstantPool pool=parseConstantPool(iter); clf.setConstPool(pool); AccessFlag accessFlag=parseAccessFlag(iter); clf.setAccessFlag(accessFlag); ClassIndex clzIndex=parseClassInfex(iter); clf.setClassIndex(clzIndex); parseInterfaces(iter); parseField(clf,iter); parseMethod(clf,iter); for(Method m:clf.getMethods()){ ByteCodeCommand [] cmds =CommandParser.parse(clf,m.getCodeAttr().getCode() ); m.getCodeAttr().setCmds(cmds); } return clf; } private AccessFlag parseAccessFlag(ByteCodeIterator iter) { int flag=iter.nextU2toInt(); AccessFlag accessFlag=new AccessFlag(flag); return accessFlag; } private ClassIndex parseClassInfex(ByteCodeIterator iter) { ClassIndex clzIndex=new ClassIndex(); int thisClassIndex=iter.nextU2toInt(); int superClassIndex=iter.nextU2toInt(); clzIndex.setSuperClassIndex(superClassIndex); clzIndex.setThisClassIndex(thisClassIndex); return clzIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iter) { ConstantPool constantPool=new ConstantPool(); int poolNum=iter.nextU2toInt(); constantPool.addConstantInfo(new NullConstantInfo()); for(int i=1;i<poolNum;i++){ int tag=iter.nextU1toInt(); if(tag==ConstantInfo.CLASS_INFO){ ClassInfo classInfo=new ClassInfo(constantPool); int nameIndex=iter.nextU2toInt(); classInfo.setUtf8Index(nameIndex); constantPool.addConstantInfo(classInfo); } else if(tag==ConstantInfo.FIELD_INFO){ FieldRefInfo field=new FieldRefInfo(constantPool); int classIndex=iter.nextU2toInt(); int nameAndTypeIndex=iter.nextU2toInt(); field.setClassInfoIndex(classIndex); field.setNameAndTypeIndex(nameAndTypeIndex); constantPool.addConstantInfo(field); } else if(tag==ConstantInfo.FLOAT_INFO){ } else if(tag==ConstantInfo.METHOD_INFO){ MethodRefInfo methodInfo=new MethodRefInfo(constantPool); int classIndex=iter.nextU2toInt(); int nameAndTypeIndex=iter.nextU2toInt(); methodInfo.setClassInfoIndex(classIndex); methodInfo.setNameAndTypeIndex(nameAndTypeIndex); constantPool.addConstantInfo(methodInfo); } else if(tag==ConstantInfo.NAME_AND_TYPE_INFO){ NameAndTypeInfo nameAndType=new NameAndTypeInfo(constantPool); int nameIndex=iter.nextU2toInt(); int nameAndTypeIndex=iter.nextU2toInt(); nameAndType.setIndex1(nameIndex); nameAndType.setIndex2(nameAndTypeIndex); constantPool.addConstantInfo(nameAndType); } else if(tag==ConstantInfo.STRING_INFO){ StringInfo stringInfo=new StringInfo(constantPool); int stringIndex=iter.nextU2toInt(); stringInfo.setIndex(stringIndex); constantPool.addConstantInfo(stringInfo); } else if(tag==ConstantInfo.UTF8_INFO){ UTF8Info utf=new UTF8Info(constantPool); int length=iter.nextU2toInt(); byte[] date=iter.getByte(length); String value = null; try { value = new String(date,"UTF-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } utf.setLength(length); utf.setValue(value); constantPool.addConstantInfo(utf); } else{ new Exception("no find tag"); } } return constantPool; } private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextU2toInt(); System.out.println("interfaceCount:" + interfaceCount); // TODO : 如果实现了interface, 这里需要解析 } private void parseField(ClassFile clf,ByteCodeIterator iter){ int fieldNum=iter.nextU2toInt(); for(int i=0;i<fieldNum;i++){ clf.addField(Field.parse(clf.getConstantPool(), iter)); } } private void parseMethod(ClassFile clf,ByteCodeIterator iter){ int methodNum=iter.nextU2toInt(); for(int i=0;i<methodNum;i++){ clf.addMethod(Method.parse(clf, iter)); } } }