java.lang.NoSuchMethodError: akka.actor.ActorCell.addFunctionRef
java.lang.NoSuchMethodError: akka.actor.ActorCell.addFunctionRef
我正在尝试设置一个简单的 akka-http 2.4.2 项目来测试它,但我没有这样做。
我的built.sbt:
import NativePackagerHelper._
lazy val akkaVersion = "2.4.2"
lazy val root = (project in file(".")).
settings(
name := "akkTest",
version := "0.1",
scalaVersion := "2.11.7")
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-http-spray-json-experimental" % akkaVersion
)
enablePlugins(JavaServerAppPackaging)
我的代码片段在 Main.scala
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer
import akka.stream.scaladsl._
import akka.actor.ActorSystem
object Main extends App {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val ec = system.dispatcher
val serverSource =
Http().bind(interface = "localhost", port = 8080)
val bindingFuture =
serverSource.to(Sink.foreach { connection => // foreach materializes the source
println("Accepted new connection from " + connection.remoteAddress)
}).run()
}
执行时抛出错误:
Uncaught error from thread [default-akka.actor.default-dispatcher-2] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[default]
java.lang.NoSuchMethodError: akka.actor.ActorCell.addFunctionRef(Lscala/Function2;)Lakka/actor/FunctionRef;
at akka.stream.stage.GraphStageLogic$StageActor.<init>(GraphStage.scala:143)
at akka.stream.stage.GraphStageLogic.getStageActor(GraphStage.scala:904)
at akka.stream.impl.io.ConnectionSourceStage$$anon.preStart(TcpStages.scala:56)
at akka.stream.impl.fusing.GraphInterpreter.init(GraphInterpreter.scala:468)
at akka.stream.impl.fusing.GraphInterpreterShell.init(ActorGraphInterpreter.scala:363)
at akka.stream.impl.fusing.ActorGraphInterpreter.tryInit(ActorGraphInterpreter.scala:502)
at akka.stream.impl.fusing.ActorGraphInterpreter.preStart(ActorGraphInterpreter.scala:539)
at akka.actor.Actor$class.aroundPreStart(Actor.scala:472)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundPreStart(ActorGraphInterpreter.scala:493)
at akka.actor.ActorCell.create(ActorCell.scala:580)
at akka.actor.ActorCell.invokeAll(ActorCell.scala:456)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:279)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at akka.dispatch.Mailbox.exec(Mailbox.scala:231)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
这一定是我环境中的问题,但我不知道如何跟踪该问题。我正在使用 jdk 1.8u71
[info] Done updating.
[info] Including from cache: ssl-config-akka_2.11-0.1.3.jar
[info] Including from cache: reactive-streams-1.0.0.jar
[info] Including from cache: akka-http-spray-json-experimental_2.11-2.4.2.jar
[info] Including from cache: config-1.3.0.jar
[info] Including from cache: spray-json_2.11-1.3.2.jar
[info] Including from cache: ssl-config-core_2.11-0.1.3.jar
[info] Including from cache: scala-parser-combinators_2.11-1.0.4.jar
[info] Including from cache: scala-java8-compat_2.11-0.7.0.jar
[info] Including from cache: akka-parsing_2.11-2.4.2.jar
[info] Including from cache: akka-http-experimental_2.11-2.4.2.jar
[info] Including from cache: akka-actor_2.11-2.4.2.jar
[info] Including from cache: akka-http-core_2.11-2.4.2.jar
[info] Including from cache: akka-stream_2.11-2.4.2.jar
[info] Including from cache: scala-library-2.11.7.jar
请记住,我只指出相同 akka 版本的依赖关系
这个程序在使用 sbt 运行 时工作正常,但在我自己的 scala 启动器
中使用组装的 jar 时失败
当这件事发生在我身上时,我通过消除对旧版 akka-actor 的传递依赖来解决它。即使依赖项对您来说看起来很明显,我还是建议您仔细查看您的依赖项树,看看是否包含早期版本的 akka-actor。
Scala 2.11 捆绑了旧版本的 akka-actor。 Scala 将他们的库置于用户创建的库之上。 Spark 可能会捆绑相同的东西,尽管在它的组装罐中。
在 scala 中,从 lib 文件夹中删除 akka jar 就足够了。在 Spark 中,利用 driver-class-path 解决问题,或利用 SQLContext 配置使用户库优先
未回答的问题是为什么这不会在所有设置中发生,因为这在家里没有发生(也许 OS 存储库没有安装带有 akka-actor 库的 scala)
问题是Spark内部使用了Akka。只要您 运行 将您的 Spark Job 作为自包含应用程序(例如 sbt run
),这就不是问题,因为将使用您自己的 Akka 版本。但是,一旦您将应用程序提交到具有 spark-submit
的集群,情况就会发生变化。然后,Spark classloader 将选择 Akka 的内部版本,而不是 sparkJob.jar
中捆绑的 Akka 实现。因此,上面的 NoSuchMethodError
来自 akka-stream_2.11-2.4.2
调用 Spark 中使用的 akka-actor_2.11-2.3.x.jar
,而不是捆绑在您的作业中的 akka-actor_2.11-2.4.2.jar
。 addFunctionRef
方法实际上非常 recent addition 并且在早期版本的 Akka 中不存在。您可以通过在异常发生的地方设置断点(或使用异常断点)来验证这一点。应用程序在 GraphStage
中的问题位置暂停,评估
materializer.supervsor.getClass().getResource("ActorCell.class")
这将打印出 class 文件 ActorCell
的加载位置。
为了确保您与 Spark 内部使用的 Akka 版本隔离,您可以使用 spark-submit
的 --driver-class-path
选项,例如
spark-submit --class MyJob \
--driver-class-path akka-actor_2.11-2.4.2.jar \
--master spark://master:7077 \
sparkJob.jar
如果你这样做,我还建议在你的 build.sbt
中将 akka-actor
设置为 "test, provided"
,这样你就不会在 [=14] 中也包含 akka-actor
=].
对于那些即使 sbt run
也会发生的人。我的解决方案是在 build.sbt
文件中添加 akka-stream
依赖项,例如:
"com.typesafe.akka" %% "akka-stream" % "2.5.3",
"com.typesafe.akka" %% "akka-stream-testkit" % "2.5.3" % Test
我在将 akka-http-experimental-2.4.11.2
与 akka-actor-2.5.6
一起使用时遇到了类似的问题。
dependencies {
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.11'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.6'
compile group: 'com.typesafe.akka', name: 'akka-http-experimental_2.11', version: '2.4.11.2'
}
问题是,akka-http-experimental-2.4.11.2
本身使用 com.typesafe.akka:akka-actor:2.4.11.2
. 被 2.5.6
.
覆盖
./gradlew dependencies
compileClasspath - Compile classpath for source set 'main'.
+--- org.scala-lang:scala-library:2.11.11
+--- com.typesafe.akka:akka-actor_2.11:2.5.6
| +--- org.scala-lang:scala-library:2.11.11
| +--- com.typesafe:config:1.3.1
| \--- org.scala-lang.modules:scala-java8-compat_2.11:0.7.0
| \--- org.scala-lang:scala-library:2.11.7 -> 2.11.11
+--- com.typesafe.akka:akka-http-experimental_2.11:2.4.11.2
| +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| \--- com.typesafe.akka:akka-http-core_2.11:2.4.11.2
| +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| +--- com.typesafe.akka:akka-stream_2.11:2.4.11.2
| | +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| | +--- com.typesafe.akka:akka-actor_2.11:2.4.11.2 -> 2.5.6 (*) <---- Ting
| | +--- com.typesafe:ssl-config-akka_2.11:0.2.1
| | | +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| | | \--- com.typesafe:ssl-config-core_2.11:0.2.1
| | | +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| | | +--- com.typesafe:config:1.2.0 -> 1.3.1
| | | \--- org.scala-lang.modules:scala-parser-combinators_2.11:1.0.4
| | | \--- org.scala-lang:scala-library:2.11.6 -> 2.11.11
| | \--- org.reactivestreams:reactive-streams:1.0.0
| \--- com.typesafe.akka:akka-parsing_2.11:2.4.11.2
| \--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
\--- org.codehaus.groovy:groovy-all:2.4.12
(*) - dependencies omitted (listed previously)
1) 一旦我将 akka-actor
版本降低到 2.4.11
,它工作正常。
dependencies {
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.11'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.4.11'
compile group: 'com.typesafe.akka', name: 'akka-http-experimental_2.11', version: '2.4.11.2'
}
2) 另一种方法是 exclude
不需要的 akka_actor
并明确添加想要的。
dependencies {
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.11'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.6'
compile group: 'com.typesafe.akka', name: 'akka-http-experimental_2.11', version: '2.4.11.2' {
exclude group: "com.typesafe.akka", module: "akka-actor_2.11" // <- exlude actor 2.4.11.2
}
}
我正在尝试设置一个简单的 akka-http 2.4.2 项目来测试它,但我没有这样做。
我的built.sbt:
import NativePackagerHelper._
lazy val akkaVersion = "2.4.2"
lazy val root = (project in file(".")).
settings(
name := "akkTest",
version := "0.1",
scalaVersion := "2.11.7")
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-http-spray-json-experimental" % akkaVersion
)
enablePlugins(JavaServerAppPackaging)
我的代码片段在 Main.scala
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer
import akka.stream.scaladsl._
import akka.actor.ActorSystem
object Main extends App {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val ec = system.dispatcher
val serverSource =
Http().bind(interface = "localhost", port = 8080)
val bindingFuture =
serverSource.to(Sink.foreach { connection => // foreach materializes the source
println("Accepted new connection from " + connection.remoteAddress)
}).run()
}
执行时抛出错误:
Uncaught error from thread [default-akka.actor.default-dispatcher-2] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[default]
java.lang.NoSuchMethodError: akka.actor.ActorCell.addFunctionRef(Lscala/Function2;)Lakka/actor/FunctionRef;
at akka.stream.stage.GraphStageLogic$StageActor.<init>(GraphStage.scala:143)
at akka.stream.stage.GraphStageLogic.getStageActor(GraphStage.scala:904)
at akka.stream.impl.io.ConnectionSourceStage$$anon.preStart(TcpStages.scala:56)
at akka.stream.impl.fusing.GraphInterpreter.init(GraphInterpreter.scala:468)
at akka.stream.impl.fusing.GraphInterpreterShell.init(ActorGraphInterpreter.scala:363)
at akka.stream.impl.fusing.ActorGraphInterpreter.tryInit(ActorGraphInterpreter.scala:502)
at akka.stream.impl.fusing.ActorGraphInterpreter.preStart(ActorGraphInterpreter.scala:539)
at akka.actor.Actor$class.aroundPreStart(Actor.scala:472)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundPreStart(ActorGraphInterpreter.scala:493)
at akka.actor.ActorCell.create(ActorCell.scala:580)
at akka.actor.ActorCell.invokeAll(ActorCell.scala:456)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:279)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at akka.dispatch.Mailbox.exec(Mailbox.scala:231)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
这一定是我环境中的问题,但我不知道如何跟踪该问题。我正在使用 jdk 1.8u71
[info] Done updating.
[info] Including from cache: ssl-config-akka_2.11-0.1.3.jar
[info] Including from cache: reactive-streams-1.0.0.jar
[info] Including from cache: akka-http-spray-json-experimental_2.11-2.4.2.jar
[info] Including from cache: config-1.3.0.jar
[info] Including from cache: spray-json_2.11-1.3.2.jar
[info] Including from cache: ssl-config-core_2.11-0.1.3.jar
[info] Including from cache: scala-parser-combinators_2.11-1.0.4.jar
[info] Including from cache: scala-java8-compat_2.11-0.7.0.jar
[info] Including from cache: akka-parsing_2.11-2.4.2.jar
[info] Including from cache: akka-http-experimental_2.11-2.4.2.jar
[info] Including from cache: akka-actor_2.11-2.4.2.jar
[info] Including from cache: akka-http-core_2.11-2.4.2.jar
[info] Including from cache: akka-stream_2.11-2.4.2.jar
[info] Including from cache: scala-library-2.11.7.jar
请记住,我只指出相同 akka 版本的依赖关系
这个程序在使用 sbt 运行 时工作正常,但在我自己的 scala 启动器
中使用组装的 jar 时失败当这件事发生在我身上时,我通过消除对旧版 akka-actor 的传递依赖来解决它。即使依赖项对您来说看起来很明显,我还是建议您仔细查看您的依赖项树,看看是否包含早期版本的 akka-actor。
Scala 2.11 捆绑了旧版本的 akka-actor。 Scala 将他们的库置于用户创建的库之上。 Spark 可能会捆绑相同的东西,尽管在它的组装罐中。
在 scala 中,从 lib 文件夹中删除 akka jar 就足够了。在 Spark 中,利用 driver-class-path 解决问题,或利用 SQLContext 配置使用户库优先
未回答的问题是为什么这不会在所有设置中发生,因为这在家里没有发生(也许 OS 存储库没有安装带有 akka-actor 库的 scala)
问题是Spark内部使用了Akka。只要您 运行 将您的 Spark Job 作为自包含应用程序(例如 sbt run
),这就不是问题,因为将使用您自己的 Akka 版本。但是,一旦您将应用程序提交到具有 spark-submit
的集群,情况就会发生变化。然后,Spark classloader 将选择 Akka 的内部版本,而不是 sparkJob.jar
中捆绑的 Akka 实现。因此,上面的 NoSuchMethodError
来自 akka-stream_2.11-2.4.2
调用 Spark 中使用的 akka-actor_2.11-2.3.x.jar
,而不是捆绑在您的作业中的 akka-actor_2.11-2.4.2.jar
。 addFunctionRef
方法实际上非常 recent addition 并且在早期版本的 Akka 中不存在。您可以通过在异常发生的地方设置断点(或使用异常断点)来验证这一点。应用程序在 GraphStage
中的问题位置暂停,评估
materializer.supervsor.getClass().getResource("ActorCell.class")
这将打印出 class 文件 ActorCell
的加载位置。
为了确保您与 Spark 内部使用的 Akka 版本隔离,您可以使用 spark-submit
的 --driver-class-path
选项,例如
spark-submit --class MyJob \
--driver-class-path akka-actor_2.11-2.4.2.jar \
--master spark://master:7077 \
sparkJob.jar
如果你这样做,我还建议在你的 build.sbt
中将 akka-actor
设置为 "test, provided"
,这样你就不会在 [=14] 中也包含 akka-actor
=].
对于那些即使 sbt run
也会发生的人。我的解决方案是在 build.sbt
文件中添加 akka-stream
依赖项,例如:
"com.typesafe.akka" %% "akka-stream" % "2.5.3",
"com.typesafe.akka" %% "akka-stream-testkit" % "2.5.3" % Test
我在将 akka-http-experimental-2.4.11.2
与 akka-actor-2.5.6
一起使用时遇到了类似的问题。
dependencies {
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.11'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.6'
compile group: 'com.typesafe.akka', name: 'akka-http-experimental_2.11', version: '2.4.11.2'
}
问题是,akka-http-experimental-2.4.11.2
本身使用 com.typesafe.akka:akka-actor:2.4.11.2
. 被 2.5.6
.
./gradlew dependencies
compileClasspath - Compile classpath for source set 'main'.
+--- org.scala-lang:scala-library:2.11.11
+--- com.typesafe.akka:akka-actor_2.11:2.5.6
| +--- org.scala-lang:scala-library:2.11.11
| +--- com.typesafe:config:1.3.1
| \--- org.scala-lang.modules:scala-java8-compat_2.11:0.7.0
| \--- org.scala-lang:scala-library:2.11.7 -> 2.11.11
+--- com.typesafe.akka:akka-http-experimental_2.11:2.4.11.2
| +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| \--- com.typesafe.akka:akka-http-core_2.11:2.4.11.2
| +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| +--- com.typesafe.akka:akka-stream_2.11:2.4.11.2
| | +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| | +--- com.typesafe.akka:akka-actor_2.11:2.4.11.2 -> 2.5.6 (*) <---- Ting
| | +--- com.typesafe:ssl-config-akka_2.11:0.2.1
| | | +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| | | \--- com.typesafe:ssl-config-core_2.11:0.2.1
| | | +--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
| | | +--- com.typesafe:config:1.2.0 -> 1.3.1
| | | \--- org.scala-lang.modules:scala-parser-combinators_2.11:1.0.4
| | | \--- org.scala-lang:scala-library:2.11.6 -> 2.11.11
| | \--- org.reactivestreams:reactive-streams:1.0.0
| \--- com.typesafe.akka:akka-parsing_2.11:2.4.11.2
| \--- org.scala-lang:scala-library:2.11.8 -> 2.11.11
\--- org.codehaus.groovy:groovy-all:2.4.12
(*) - dependencies omitted (listed previously)
1) 一旦我将 akka-actor
版本降低到 2.4.11
,它工作正常。
dependencies {
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.11'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.4.11'
compile group: 'com.typesafe.akka', name: 'akka-http-experimental_2.11', version: '2.4.11.2'
}
2) 另一种方法是 exclude
不需要的 akka_actor
并明确添加想要的。
dependencies {
compile group: 'org.scala-lang', name: 'scala-library', version: '2.11.11'
compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.6'
compile group: 'com.typesafe.akka', name: 'akka-http-experimental_2.11', version: '2.4.11.2' {
exclude group: "com.typesafe.akka", module: "akka-actor_2.11" // <- exlude actor 2.4.11.2
}
}