我正在尝试实现分析(扩展 DefaultOneStepAnalysis)以在 CHA 算法中构造调用图。我的代码分为三部分:
1) method "doAnalyze" to return the "BasicReport"
2) method "analyze" to find call edges for each method in the given project
3) class "AnalysisContext" to store the context and methods using in the analysis.
在 3) 中,我使用方法“callBySignature”来找出与“CHACallGraphExtractor”相同的方法的 cbsMethods,但它不返回预期结果。虽然我使用原始 OPAL 的方式在 Extractor 中获取 cbsMethods,但结果是一组方法。
你能帮我确认问题出在哪里以及如何解决吗?非常感谢。
问候,江
----我的代码的主要部分---------------------------------------- --------
object CHACGAnalysis extends DefaultOneStepAnalysis {
... ...
override def doAnalyze(
project: Project[URL],
parameters: Seq[String] = List.empty,
isInterrupted: () ⇒ Boolean
): BasicReport = {
... ...
for {
classFile <- project.allProjectClassFiles
method <- classFile.methods
} {
analyze(project, methodToCellCompleter, classFile, method))
}
... ...
}
def analyze(
project: Project[URL],
methodToCellCompleter: Map[(String,Method), CellCompleter[K, Set[Method]]],
classFile: ClassFile,
method: Method
): Unit = {
… …
val context = new AnalysisContext(project, classFile, method)
method.body.get.foreach((pc, instruction) ⇒
instruction.opcode match {
... ...
case INVOKEINTERFACE.opcode ⇒
val INVOKEINTERFACE(declaringClass, name, descriptor) = instruction
context.addCallEdge_VirtualCall(pc, declaringClass, name, descriptor, true,cell1)
... ...
}
… …
}
protected[this] class AnalysisContext(
val project: SomeProject,
val classFile: ClassFile,
val method: Method
) {
val classHierarchy = project.classHierarchy
val cbsIndex = project.get(CallBySignatureResolutionKey)
val statistics = project.get(IntStatisticsKey)
val instantiableClasses = project.get(InstantiableClassesKey)
val cache = new CallGraphCache[MethodSignature, scala.collection.Set[Method]](project)
private[AnalysisContext] def callBySignature(
declaringClassType: ObjectType,
name: String,
descriptor: MethodDescriptor
): Set[Method] = {
val cbsMethods = cbsIndex.findMethods(
name,
descriptor,
declaringClassType
)
cbsMethods
}
def addCallEdge_VirtualCall(
pc: PC,
declaringClassType: ObjectType,
name: String,
descriptor: MethodDescriptor,
isInterfaceInvocation: Boolean = false,
cell1: CellCompleter[K, Set[Method]]
): Unit = {
val cbsCalls =
if (isInterfaceInvocation) {
callBySignature(declaringClassType, name, descriptor)
}
else
Set.empty[Method]
… …
}
… …
}