在Java中执行RFC计算的算法

时间:2020-03-05 18:41:30  来源:igfitidea点击:

Java类的RFC是所有方法的集合,可以响应对类对象的消息或者类中的某些方法来调用所有方法。
RFC = M + R其中
M =类中方法的数量。
R =从M直接调用的其他方法的总数。

认为C是.class,而J是.java文件,我们需要计算该文件的RFC。

class J{

 a(){}
 b(){}
 c(){
   e1.e();
   e1.f();
   e1.g();
 }
 h(){
   i.k();
   i.j();
  }
  m(){}
  n(){
   i.o();
   i.p();
   i.p();
   i.p();
  }
}

这里M = 6
和R = 9(不必担心循环内的调用。它被视为单个调用)

计算M很容易。使用类加载器加载C并使用反射获取方法计数。

计算R不是直接的。我们需要计算从类中进行方法调用的次数。仅第一级。

为了计算R,我必须使用正则表达式。通常格式为(不使用。的呼叫不计算在内)

[variable_name].[method_name]([zero or more parameters]);

或者

[variable_name].[method_name]([zero or more parameters])

当调用返回直接成为另一个方法的参数时,没有分号。
或者

[variable_name].[method_name]([zero or more parameters]).method2();

这成为两个方法调用

我们还能想到方法调用的其他哪些模式?除了使用RegEx以外,还有其他方法可用于计算R。

更新:
@麦道威尔
看起来像使用BCEL,我可以简化整个过程。我来试试看

解决方案

回答

我们应该在Java语言规范中找到答案。

我们忘记了静态方法调用,参数内部的方法调用...

回答

使用反射调用方法(方法的名称在字符串中)。

回答

我们可以将字节码工程库与二进制文件一起使用。我们可以使用DescendingVisitor访问类的成员和引用。我用它来查找类依赖。

或者,我们可以重用某些模型的源文件。我很确定Eclipse JDT中的Java编辑器支持某种形式的模型。

回答

M是否包括对其自身方法的调用?还是调用内部类?例如:

class J {
  a() { }
  b() { this.a(); }
  c() { jj.aa(); }
  d() { i.k(); }
  e() { this.f().a(); }
  f() { return this; }
  g() { i.m().n(); }

  class JJ {
    aa() { a(); }
  }
}

它的M值是多少?对该类中未定义的方法只有三个函数调用(d()和g()函数中的调用)。我们是否要包括对内部类的调用,或者对内部类中进行的主类的调用?我们是否要包括对同一类的其他方法的调用?

如果我们正在查看任何方法调用,而不论其来源如何,那么正则表达式都可能起作用,但是要正确处理就很难了(正则表达式是否正确忽略了包含类似方法调用内容的字符串?它是否正确处理了构造函数调用?)。如果我们关心方法调用的来源,则正则表达式可能无法满足需求。我们需要使用反射(尽管遗憾的是,我对反射的了解还不足以在此提供帮助)。