通过使用BCEL解析Java字节码来确定LCOM4(方法中缺乏内聚)



>我构建了一个程序,它接收提供的".class"文件并使用BCEL对其进行解析,但是在使用结果对象确定LCOM4值时,我有点迷茫。我已经搜索了整个网络,试图找到一个合适的教程,但到目前为止我无法(我也阅读了关于 BCEL 的整个 javadoc(。因此,我需要有关此问题的一些帮助,例如一些详细的教程或代码片段,可以帮助我了解如何执行此操作。

好的,让我们定义一个类来表示一组字段和方法:

public class Group {
    private final Set<String> fields = new HashSet<>();
    private final Set<String> methods = new HashSet<>();
    public Group addFields(String...fields) {
        for (String field: fields) {
            this.fields.add(field);
        }
        return this;
    }
    public Group addMethods(String... methods) {
        for (String method: methods) {
            this.methods.add(method);
        }
        return this;
    }
    public int fields() {
        return fields.size();
    }
    public int methods() {
        return methods.size();
    }
    public boolean intersects(Group other) {
        for (String field: other.fields) {
            if (fields.contains(field)) {
                return true;
            }
        }
        for (String method: other.methods) {
            if (methods.contains(method)) {
                return true;
            }
        }
        return false;
    }
    public void merge(Group other) {
        fields.addAll(other.fields);
        methods.addAll(other.methods);
    }
    @Override
    public String toString() {
        return "Group{" + "fields=" + fields + ", methods=" + methods + '}';
    }
}

我们首先为类中定义的每个字段填充组列表,然后,对于每个方法,我们使用代码中引用的字段和方法构建一个组,然后通过合并和删除与方法组相交的每个组来减少组列表。

这是加载类组的java代码。 LCOM4 是 groups.size((:

private List<Group> loadGroups(File file) throws IOException {
    try (InputStream in = new FileInputStream(file)) {
        ClassParser parser = new ClassParser(in, file.getName());
        JavaClass clazz = parser.parse();
        String className = clazz.getClassName();
        ConstantPoolGen cp = new ConstantPoolGen(clazz.getConstantPool());
        List<Group> groups = new ArrayList<Group>();
        for (Field field: clazz.getFields()) {
            groups.add(new Group().addFields(field.getName()));
        }
        for (Method method: clazz.getMethods()) {
            Group group = new Group().addMethods(method.getName());
            Code code = method.getCode();
            InstructionList instrs = new InstructionList(code.getCode());
            for (InstructionHandle ih: instrs) {
                Instruction instr = ih.getInstruction();
                if (instr instanceof FieldInstruction) {
                    FieldInstruction fld = (FieldInstruction)instr;
                    if (fld.getClassName(cp).equals(className)) {
                        group.addFields(fld.getFieldName(cp));
                    }
                } else if (instr instanceof InvokeInstruction) {
                    InvokeInstruction inv = (InvokeInstruction)instr;
                    if (inv.getClassName(cp).equals(className)) {
                        group.addMethods(inv.getMethodName(cp));
                    }
                }
            }
            if (group.fields() > 0 || group.methods() > 1) {
                int i = groups.size();
                while (i > 0) {
                    --i;
                    Group g = groups.get(i);
                    if (g.intersects(group)) {
                        group.merge(g);
                        groups.remove(i);
                    }
                }
                groups.add(group);
            }
        }
        return groups;
    }
}

相关内容

  • 没有找到相关文章

最新更新