我有一个项目在版本2.11_22.5.21中使用akka,它是在我的胖罐子中组装的。
我已经下载了scala二进制2.11.12,它附带了lib/akka-actor_2.11-2.3.16.jar
(bin/scala
旁边(
当我运行我的项目:scala -cp target/scala-2.11/project-assembly-2.4.0.jar foo.MyClass
时,我得到
java.lang.NoSuchMethodError: akka.actor.OneForOneStrategy.withMaxNrOfRetries(I)Lakka/actor/OneForOneStrategy;
如果我在scala目录中删除lib/akka-actor_2.11-2.3.16.jar
,它就可以工作了。
当然,它也适用于sbt运行,因为sbt使用了自己的scala版本。
为什么scala二进制文件使用自己的akka版本,而不是fat jar中提供的版本?
假设;Scala二进制";你指的是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
则CCD_ 5中的所有内容将优先于您使用CCD_ 6指定的内容。要了解这一点,请分析以下bin/scala
runner脚本的片段
execCommand
"${JAVACMD:=java}"
$JAVA_OPTS
"${java_args[@]}"
"${classpath_args[@]}"
-Dscala.home="$SCALA_HOME"
$OVERRIDE_USEJAVACP
"$EMACS_OPT"
$WINDOWS_OPT
scala.tools.nsc.MainGenericRunner "$@"
请注意,保存lib
的jar的"${classpath_args[@]}"
位于保存参数(如-cp
(的最后一个"$@"
之前。最后,JVM将选择它在类路径上找到的第一个匹配类,在您的情况下,它将是lib/akka-actor_2.11-2.3.16.jar
中的一个。例如
scala -cp target/scala-2.11/project-assembly-2.4.0.jar
将扩展到类似的东西
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
因此CCD_ 13将优先于CCD_。