Search code examples
androidscalareflectiondependenciesrmi

Scala reflection java.rmi dependency, can it work on Android?


I would like to use the Scala (2.11) reflection package's runtime mirror in a Scala application compiled for android which is being build using Scala on android.

I was able to fiddle with ProGuard options in order to make it include the required Scala classes. However when I try to get a mirror instance:

universe.runtimeMirror(this.getClass.getClassLoader)

(Indeed it fails during the lazy computation of universe)

The application crashes in run time:

java.lang.NoClassDefFoundError: Failed resolution of: Ljava/rmi/Remote;
at     scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass$lzycompute(Definitions.scala:370)
at     scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass(D    efinitions.scala:370)
at     scala.reflect.runtime.JavaUniverseForce$class.force(JavaUniverseForce.scal    a:255)
at     scala.reflect.runtime.JavaUniverse.force(JavaUniverse.scala:16)
at     scala.reflect.runtime.JavaUniverse.init(JavaUniverse.scala:147)
at     scala.reflect.runtime.JavaUniverse.<init>(JavaUniverse.scala:78)
at     scala.reflect.runtime.package$.universe$lzycompute(package.scala:17)
at     scala.reflect.runtime.package$.universe(package.scala:17)

This crash is for me as expected as it isn't:

It is expected as java.rmi is not part of the Android API and I should expect any code trying to load its classes to crash.

It is unexpected as I didn't know that Scala's reflect package used java.rmi

I have traced the code to were rmi is required, that is to JavaUniverse (a trait mixed in JavaUniverse class) force method:

...
definitions.RemoteInterfaceClass
...

Which leads to DefinitionsClass:

lazy val RemoteInterfaceClass  = requiredClass[java.rmi.Remote]

Am I wrong to think that this is a no-go for Scala reflection in Android? If I am, what could be a workaround to this problem?


Solution

  • To summarize your solution and a related solution, it is sufficient to add two files, and modify build.sbt to include:

    dexAdditionalParams in Android += "--core-library"
    

    Add java/rmi/Remote.java to your project with the content:

    package java.rmi;
    public interface Remote {}
    

    Add java/rmi/RemoteException.java to your project with the content:

    package java.rmi;
    public interface RemoteException {}