package io.github.vxzh.jvm.loader; import io.github.vxzh.jvm.clz.AccessFlag; import io.github.vxzh.jvm.clz.ClassFile; import io.github.vxzh.jvm.clz.ClassIndex; import io.github.vxzh.jvm.clz.ConstantPool; import io.github.vxzh.jvm.constant.*; public class ClassFileParser { public ClassFile parse(byte[] codes) { ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes); String magicNumber = byteCodeIterator.nextU4ToHexString(); if (!"cafebabe".equals(magicNumber)) throw new RuntimeException("This is not a Java Class file!"); ClassFile classFile = new ClassFile(); int minorVersion = byteCodeIterator.nextU2ToInt(); classFile.setMinorVersion(minorVersion); int majorVersion = byteCodeIterator.nextU2ToInt(); classFile.setMajorVersion(majorVersion); classFile.setConstPool(this.parseConstantPool(byteCodeIterator)); classFile.setAccessFlag(this.parseAccessFlag(byteCodeIterator)); classFile.setClassIndex(this.parseClassInfex(byteCodeIterator)); return classFile; } private AccessFlag parseAccessFlag(ByteCodeIterator iterator) { return new AccessFlag(iterator.nextU2ToInt()); } private ClassIndex parseClassInfex(ByteCodeIterator iterator) { ClassIndex classIndex = new ClassIndex(); classIndex.setThisClassIndex(iterator.nextU2ToInt()); classIndex.setSuperClassIndex(iterator.nextU2ToInt()); return classIndex; } private ConstantPool parseConstantPool(ByteCodeIterator iterator) { int constantCount = iterator.nextU2ToInt(); ConstantPool constantPool = new ConstantPool(); constantPool.addConstantInfo(new NullConstantInfo()); for (int i = 0; i < constantCount; i++) { int tag = iterator.nextU1ToInt(); switch (tag) { case ConstantInfo.CONSTANT_CLASS_INFO: ClassInfo classInfo = new ClassInfo(constantPool); classInfo.setNameIndex(iterator.nextU2ToInt()); constantPool.addConstantInfo(classInfo); System.out.println("classInfo " + classInfo.getNameIndex()); break; case ConstantInfo.CONSTANT_UTF8_INFO: UTF8Info utf8Info = new UTF8Info(constantPool); utf8Info.setLength(iterator.nextU2ToInt()); utf8Info.setValue(iterator.nextBytesToString(utf8Info.getLength())); constantPool.addConstantInfo(utf8Info); System.out.println("utf-8 " + utf8Info.getValue()); break; case ConstantInfo.CONSTANT_METHODREF_INFO: MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); methodRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); methodRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); constantPool.addConstantInfo(methodRefInfo); System.out.println("method ref " + methodRefInfo.getClassInfoIndex() + " " + methodRefInfo.getNameAndTypeIndex()); break; case ConstantInfo.CONSTANT_NAMEANDTYPE_INFO: NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); nameAndTypeInfo.setNameIndex(iterator.nextU2ToInt()); nameAndTypeInfo.setDescriptorIndex(iterator.nextU2ToInt()); constantPool.addConstantInfo(nameAndTypeInfo); System.out.println("name and type " + nameAndTypeInfo.getNameIndex() + " " + nameAndTypeInfo.getDescriptorIndex()); break; case ConstantInfo.CONSTANT_FIELDREF_INFO: FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); fieldRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); fieldRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); constantPool.addConstantInfo(fieldRefInfo); System.out.println("field ref " + fieldRefInfo.getClassInfoIndex() + " " + fieldRefInfo.getNameAndTypeIndex()); break; case ConstantInfo.CONSTANT_STRING_INFO: StringInfo stringInfo = new StringInfo(constantPool); stringInfo.setIndex(iterator.nextU2ToInt()); constantPool.addConstantInfo(stringInfo); System.out.println("string " + stringInfo.getIndex()); break; default: //throw new RuntimeException("the constant Pool tag "+tag+" has not been implement yet!"); } } return constantPool; } }