Private method name mangling in scala

name mangling

Name mangling is a technique adopted by compiler to ensure the uniqueness of names. In the context of jvm, name is compiled to a different name in byte code compared to the original one in source code.

I am aware of this technique when I unit test of a private method in scala. I tried to invoke the method by reflect, but it reports NoSuchMethodException.

Below is a simplified example for demonstration. Private method foo is defined and is called in the InnerClass. After compilation, foo will be mangled to another name as PrivateMethod$$foo.

import java.lang.reflect.Method

class PrivateMethod {
  private def foo(a: Int): Int = a

  class Inner {
    def f(): Unit = {
      foo(1)
    }
  }
}

object PrivateMethod {
  def main(args: Array[String]): Unit = {
		// NoSuchMethodException
    val foo: Method = classOf[PrivateMethod].getDeclaredMethod("foo", classOf[Int])
    foo.setAccessible(true)
    val obj = new PrivateMethod
    val ret = foo.invoke(obj, Integer.valueOf(1))
    println(ret)
  }
}

Let’s check the javap output. The private method turns into a public method with new name. That’s why the private method cannot be found by reflect.

So how to test private method?

Use the PrivateMethodTester trait in scalatest. The method will be resolved not only by its original name but also the name prefixed with $$. See below:

Note that if the private method is not called within an inner class, its name will not be mangled.