Virtual Call Resolution does not work correctly for private methods
Issue #179
new
ProjectLike's virtualCall
resolution does not work in the following code evolution scenario. The JVM runs this code (please see the attached files. B has a main).
Class Structure
class A {
protected void method(){\* do something*\}
}
class B extends A {
private void method(){/* do something*/}
public static void main(String ... args) {
var B = new B();
b.method(); // this is an INVOKEVIRTUAL
}
}
Problem: b.method
is resolved to A.method
when an invokevirtual is used.
sbt console code leading to this error:
val file = new java.io.File(dir)
val project = org.opalj.br.analyses.Project(file)
val methods = project.allMethodsWithBody
val main = methods.filter(_.name =="main")
val body = main.body.get
val invoke = body.collectFirst{
case x @ INVOKEVIRTUAL(org.opalj.br.ObjectType("B"),"m", _) => x
}.get
val results = project.virtualCall("", invoke)
OUTPUT: results: scala.collection.Set[org.opalj.br.Method] = Set(protected void m())
The respective classfiles are attached. "StrangeCallCreator.scala" is the DSL script that engineered these classes.
Comments (2)
-
reporter -
Since Java 11, the JVM spec changed the method selection semantics, s.t. it also considers private methods on
invokevirtual
. Thus, the example can also occur without evolution. - Log in to comment
To address this issue,
ProjectLike.virtualCall
also needs to the caller's class type. I don't see any other way. Does anybody has another idea?