package jvm.classfile.method; import jvm.classfile.AccessFlag; import jvm.classfile.ClassFile; import jvm.classfile.attribute.item.AttributeInfo; import jvm.classfile.attribute.item.impl.CodeAttr; import jvm.classfile.attribute.parser.AttributeParser; import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.impl.UTF8Info; import jvm.command.CommandParser; import jvm.command.item.ByteCodeCommand; import jvm.util.ByteCodeIterator; import jvm.util.TypeUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Method { private AccessFlag accessFlag; private int nameIndex; private int descriptorIndex; private ConstantPool constantPool; private List<AttributeInfo> attributes = new ArrayList<>(); private ByteCodeCommand[] commands; public Method(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool constantPool) { this.accessFlag = new AccessFlag(accessFlag); this.nameIndex = nameIndex; this.descriptorIndex = descriptorIndex; this.constantPool = constantPool; } public static Method parse(ByteCodeIterator iterator, ClassFile classFile) { int access = iterator.nextU2ToInt(); int name = iterator.nextU2ToInt(); int descriptor = iterator.nextU2ToInt(); int attrCount = iterator.nextU2ToInt(); Method result = new Method(access, name, descriptor, classFile.getConstantPool()); for (int i = 0; i < attrCount; ++i) { result.attributes.add(AttributeParser.parse(iterator, classFile.getConstantPool())); } CodeAttr codeAttr = (CodeAttr) result.attributes.stream() .filter(a -> a instanceof CodeAttr).findFirst().orElse(null); if (codeAttr != null) { result.commands = CommandParser.parse(classFile, codeAttr.getCode()); } return result; } public String[] getParamTypes() { String str = getParamAndReturnType(); str = str.substring(str.indexOf('(') + 1, str.lastIndexOf(')')); String[] split = Arrays.stream(str.split("[L;]")) .filter(s -> !"".equals(s)) .toArray(String[]::new); List<String> result = new ArrayList<>(); Arrays.stream(split).forEach(s -> result.add(s.length() == 1 ? TypeUtils.parse(s) : s)); return result.toArray(new String[result.size()]); } public int getParamCount() { return getParamTypes().length; } public AccessFlag getAccessFlag() { return accessFlag; } public ConstantPool getConstantPool() { return constantPool; } public int getNameIndex() { return nameIndex; } public List<AttributeInfo> getAttributes() { return attributes; } public int getDescriptorIndex() { return descriptorIndex; } public ByteCodeCommand[] getCommands() { return commands; } public String getName() { return ((UTF8Info) getConstantPool().getConstantInfo(getNameIndex())).getValue(); } public String getParamAndReturnType() { return ((UTF8Info) getConstantPool().getConstantInfo(getDescriptorIndex())).getValue(); } @Override public String toString() { return getName() + ':' + getParamAndReturnType(); } }