在Java中执行RFC计算的算法
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()函数中的调用)。我们是否要包括对内部类的调用,或者对内部类中进行的主类的调用?我们是否要包括对同一类的其他方法的调用?
如果我们正在查看任何方法调用,而不论其来源如何,那么正则表达式都可能起作用,但是要正确处理就很难了(正则表达式是否正确忽略了包含类似方法调用内容的字符串?它是否正确处理了构造函数调用?)。如果我们关心方法调用的来源,则正则表达式可能无法满足需求。我们需要使用反射(尽管遗憾的是,我对反射的了解还不足以在此提供帮助)。