Virtual Call Resolution does not work correctly for private methods

Issue #179 new
Michael Reif created an issue

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)

  1. Michael Reif reporter

    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?

  2. florian_kuebler

    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.

  3. Log in to comment