Benjamin
Benjamin

Reputation: 3477

scala is using akka shipped with binary distribution instead of sbt 's one

I have a project that uses akka in version 2.11_2.5.21 which is assembly in my fat jar.

I have download the scala binary 2.11.12 and it is shipped with a lib/akka-actor_2.11-2.3.16.jar (next to bin/scala)

When I run my project : scala -cp target/scala-2.11/project-assembly-2.4.0.jar foo.MyClass I get

java.lang.NoSuchMethodError: akka.actor.OneForOneStrategy.withMaxNrOfRetries(I)Lakka/actor/OneForOneStrategy;

If i remove lib/akka-actor_2.11-2.3.16.jar in my scala directory it works.

Of course it also works with sbt run as sbt used its own scala version.

Why does scala binary use its own akka version instead of the one shipped in the fat jar?

Upvotes: 3

Views: 85

Answers (1)

Mario Galic
Mario Galic

Reputation: 48420

Assuming by "Scala binary" you are referring to the decompressed structure of say https://downloads.lightbend.com/scala/2.11.12/scala-2.11.12.tgz

➜  scala-2.11.12 tree -L 2
.
├── bin
│   ├── fsc
│   ├── fsc.bat
│   ├── scala
│   ├── scala.bat
│   ├── scalac
│   ├── scalac.bat
│   ├── scaladoc
│   ├── scaladoc.bat
│   ├── scalap
│   └── scalap.bat
├── doc
│   ├── LICENSE.md
│   ├── License.rtf
│   ├── README
│   ├── licenses
│   └── tools
├── lib
│   ├── akka-actor_2.11-2.3.16.jar
│   ├── config-1.2.1.jar
│   ├── jline-2.14.3.jar
│   ├── scala-actors-2.11.0.jar
│   ├── scala-actors-migration_2.11-1.1.0.jar
│   ├── scala-compiler.jar
│   ├── scala-continuations-library_2.11-1.0.2.jar
│   ├── scala-continuations-plugin_2.11.12-1.0.2.jar
│   ├── scala-library.jar
│   ├── scala-parser-combinators_2.11-1.0.4.jar
│   ├── scala-reflect.jar
│   ├── scala-swing_2.11-1.0.2.jar
│   ├── scala-xml_2.11-1.0.5.jar
│   └── scalap-2.11.12.jar
└── man
    └── man1

then everything inside lib/ will take precedence over what you specify with -cp. To see this analyse the following snippet of bin/scala runner script

execCommand \
  "${JAVACMD:=java}" \
  $JAVA_OPTS \
  "${java_args[@]}" \
  "${classpath_args[@]}" \
  -Dscala.home="$SCALA_HOME" \
  $OVERRIDE_USEJAVACP \
  "$EMACS_OPT" \
  $WINDOWS_OPT \
   scala.tools.nsc.MainGenericRunner  "$@"

Note that "${classpath_args[@]}" which holds jars from lib precedes the last "$@" which holds your arguments such as -cp. Finally JVM will pick the first matching class it finds on the classpath which in your case will be the one from lib/akka-actor_2.11-2.3.16.jar. For example

scala -cp target/scala-2.11/project-assembly-2.4.0.jar 

would expand to something like

java -Xbootclasspath/a:/scala-2.11.12/lib/akka-actor_2.11-2.3.16.jar ... scala.tools.nsc.MainGenericRunner -cp target/scala-2.11/project-assembly-2.4.0.jar

hence Xbootclasspath would take precedence over -cp.

Upvotes: 3

Related Questions