Scala编写Minecraft Sponge插件时出现NoSuchMethodError问题求助
java.lang.NoSuchMethodError错误 我之前也碰到过一模一样的问题,结合你的场景拆解下来,这个错误的根源其实很明确——运行环境缺少Scala标准库的支持,下面给你详细说明原因和解决步骤:
问题原因分析
你定义的case class Permission(node: String)是Scala的样例类,这类类默认会继承scala.Product特质,但Sponge的Minecraft服务器运行环境本身并没有内置Scala标准库。当服务器加载你的插件时,JVM找不到scala.Product类的初始化方法$init$,就会抛出java.lang.NoSuchMethodError。
至于你提到的for循环、隐式类也出现类似错误,是因为这些Scala语法糖背后都依赖Scala标准库的底层实现:
- for循环会被编译成
foreach/flatMap等方法调用,依赖Scala集合类 - 隐式类的实现涉及Scala的类型系统和类加载逻辑,同样需要标准库支持
解决方法:将Scala标准库打包进插件Jar
正如你已经发现的,解决这个问题的核心是把Scala标准库和你的插件代码打包到同一个Jar文件(也就是常说的"fat jar")里,让服务器能加载到所有依赖的Scala类。具体用sbt实现的步骤如下:
1. 添加sbt-assembly插件
在项目根目录下的project/plugins.sbt文件中添加插件依赖:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0")
(这个版本兼容sbt 1.x,和你用的1.0.4适配性很好)
2. 配置Jar合并策略
在build.sbt中添加合并策略,避免打包时出现META-INF文件冲突:
assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first }
3. 生成Fat Jar
在项目根目录下运行sbt命令:
sbt assembly
执行完成后,你会在target/scala-2.12目录下找到一个包含所有依赖的Jar文件(文件名通常是[项目名]-assembly-0.1.jar这类格式)。
4. 替换插件Jar
把生成的fat Jar放到Sponge服务器的plugins目录下,替换原来的插件Jar,重新启动服务器即可解决错误。
验证
启动服务器后,你会发现Permission样例类的初始化错误消失,for循环、隐式类也能正常工作了——因为现在服务器可以加载到所有需要的Scala标准库类。
内容的提问来源于stack exchange,提问作者mysterymyster

