Here is a question related to the algorithm of constructing the call graph for Java bytecode using CHA.
As there is no concrete method implementation for methods in abstract classes, adding a call edge to such methods might be a bit misleading.
take junit-4.12.jar
for instance. runFailed
has been defined in junit.runner.BaseTestRunner
which is an abstract class. Besides, there are calls to runFailed
in method getTest
which also defined in junit.runner.BaseTestRunner
While in "Assumption Hierarchy for a CHA Call Graph Construction Algorithm"(Jason&Atanas), it is said that
"given a call site x.m(), where the declared type of x is C, the possible runtime type of x must be a non-abstract subtype of C."
As far as i'm considered, without add a call edge(Calledge1) from junit.runner.BaseTestRunner getTest
to junit.runner.BaseTestRunner runFailed
, it is more reasonable to add a call edge(Calledge2) from junit.runner.BaseTestRunner getTest
to junit/textui/TestRunner runFailed
as TestRunner extends BaseTestRunner.
While after running test code to get the result of CallGraph.calledByStatistics(), only Calledge1 has been found. Calledge2 is missing.
Is there anybody can do me a favor to confirm this? Thank you in advance.
Regards,
Jiang
I found OPAL offers two views of call graph. The second one won't add a "library-call" edge into call edge.
In CallGraph.calledByStatistics()
The binding is between Callsite (PC) to caller.method for example: between “INVOKEVIRTUAL(junit.runner.BaseTestRunner{ void runFailed(java.lang.String) })” and junit/runner/BaseTestRunner.public junit.framework.Test getTest(java.lang.String)
In CallGraph.callsStatistics()
The binding is between subtype.method to caller.method for example: between "junit/textui/TestRunner.protected void runFailed(java.lang.String)” and “junit/runner/BaseTestRunner.public junit.framework.Test getTest(java.lang.String)”