使用scalac vs sbt编译和运行jar?

时间:2018-03-16 21:56:05

标签: java scala sbt sbt-assembly

我正在尝试根据this stackoverflow post为我的Scala项目编译包含所有依赖项的胖jar,以便我可以在Java应用程序中使用它。我是Scala / Java / JVM的新手,所以请耐心等待。我正在使用IntelliJ和scala 2.12.4,但是我正在从OS X终端运行sbt命令。

首先,我可以运行sbt assembly并在padsystem-assembly-0.0.1.jar中获得/target/scala-2.12/。 (我必须制作一个assembly.sbt并使用“合并策略”修改我的build.sbt以使其正常工作。)但是当我尝试使用scala运行此jar时

computer: dir user$ scala target/scala-2.12/padsystem-assembly-0.0.1.jar
scala target/scala-2.12/padsystem-assembly-0.0.1.jar 
java.lang.NullPointerException
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at scala.reflect.internal.util.ScalaClassLoader.$anonfun$tryClass$1(ScalaClassLoader.scala:45)
    at scala.util.control.Exception$Catch.$anonfun$opt$1(Exception.scala:242)
    at scala.util.control.Exception$Catch.apply(Exception.scala:224)
    at scala.util.control.Exception$Catch.opt(Exception.scala:242)
    at scala.reflect.internal.util.ScalaClassLoader.tryClass(ScalaClassLoader.scala:45)
    at scala.reflect.internal.util.ScalaClassLoader.tryToInitializeClass(ScalaClassLoader.scala:41)
    at scala.reflect.internal.util.ScalaClassLoader.tryToInitializeClass$(ScalaClassLoader.scala:41)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.tryToInitializeClass(ScalaClassLoader.scala:125)
    at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:92)
    at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:91)
    at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:125)
    at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:22)
    at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:21)
    at scala.tools.nsc.JarRunner$.run(MainGenericRunner.scala:14)
    at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:29)
    at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:28)
    at scala.tools.nsc.JarRunner$.runAndCatch(MainGenericRunner.scala:14)
    at scala.tools.nsc.JarRunner$.runJar(MainGenericRunner.scala:26)
    at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72)
    at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85)
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

当我尝试用java运行它时(这是我的主要目标):

computer: dir user$ java target/scala-2.12/padsystem-assembly-0.0.1.jar 
Error: Could not find or load main class target.scala-2.12.padsystem-assembly-0.0.1.jar

现在,在你问“你确定你的代码有效吗?”之前,我会注意到我能够成功sbt run我的代码,我也可以sbt compile和{{1它也成功了。

有趣的是,如果我尝试从基目录sbt package

sbt compile src/main/scala/OdinExtractor.scala

或者如果我sbt compile src/main/scala/OdinExtractor.scala [info] Loading settings from idea.sbt ... [info] Loading global plugins from /Users/user/.sbt/1.0/plugins [info] Loading project definition from /Users/user/PAD_IE/project/project [info] Loading settings from assembly.sbt,plugins.sbt ... [info] Loading project definition from /Users/user/PAD_IE/project [info] Loading settings from build.sbt ... [info] Set current project to padsystem (in build file:/Users/user/PAD_IE/) [info] Executing in batch mode. For better performance use sbt's shell [success] Total time: 4 s, completed Mar 16, 2018 3:35:49 PM [error] Expected ID character [error] Not a valid command: src (similar: set) [error] Expected project ID [error] Expected configuration [error] Expected ':' (if selecting a configuration) [error] Expected key [error] Not a valid key: src (similar: sources, ps, run) [error] src/main/scala/OdinExtractor.scala [error] ^ ,如果我scalac src/main/scala/OdinExtractor.scala进入cd目录并尝试运行src/main/scala,我会: p>

sbt compile OdinExtractor.scala

为什么我能够成功[info] Loading settings from idea.sbt ... [info] Loading global plugins from /Users/user/.sbt/1.0/plugins [info] Updating ProjectRef(uri("file:/Users/user/.sbt/1.0/plugins/"), "global-plugins")... [info] Done updating. [info] Set current project to scala (in build file:/Users/user/PAD_IE/src/main/scala/) [info] Executing in batch mode. For better performance use sbt's shell [info] Compiling 1 Scala source to /Users/user/PAD_IE/src/main/scala/target/scala-2.12/classes ... [error] /Users/user/PAD_IE/src/main/scala/OdinExtractor.scala:3:12: object clulab is not a member of package org [error] import org.clulab.odin.Mention [error] ^ [error] /Users/user/PAD_IE/src/main/scala/OdinExtractor.scala:4:12: object clulab is not a member of package org [error] import org.clulab.processors.Document [error] ^ [error] /Users/user/PAD_IE/src/main/scala/OdinExtractor.scala:5:12: object vinci is not a member of package org [error] import org.vinci.pad.padsystem.PadSystem [error] ^ [error] three errors found [error] (Compile / compileIncremental) Compilation failed [error] Total time: 1 s, completed Mar 16, 2018 3:38:06 PM 我的代码,但无法使用scala或java运行jar,特别是当所有依赖项都包含在fat jar中时?

当我sbt runscalac src/main/scala/OdinExtractor.scala时,为什么我的依赖项出现错误?我猜的第一个因为sbt compile OdinExtractor.scala想要像

这样的东西

scalac

(顺便说一句,我无法弄清楚如何做到这一点......)

根据我的理解,这就是我们开始使用scalac -cp "all:of:the:classpath:stuff:ever" OdinExtractor.scala的原因,是吗?避免凌乱的类路径的东西。这让我想到了下一个问题:为什么sbt在指向特定文件时会失败?当我从sbt compile目录运行它时,为什么会失败?我不知道第一个问题,但我对第二个问题的猜测是src/main/scala必须总是从基本目录运行?

回到主要目标:生成一个可以用Java运行的胖罐...有谁知道如何调试这个?我不明白为什么程序集jar失败,但代码仍然运行sbt。我原本认为调试这个的最好方法是用sbt run编译对象,并尝试用Scala和Java运行它,但事实证明这非常麻烦。

最后,我有一种令人毛骨悚然的感觉,也许所有这一切都可归结为1)我对def main()的混淆,或者2)也许是我的项目结构?但由于我的东西与classpaths一起运行,我只是完全失败了...请帮忙!如果我需要添加到帖子中以使其更清晰,请告诉我。谢谢!

编辑 - 根据我的sbt run,我确实包含了build.sbt jar,因此它可以被Java解析。 即scala-library

此外,如果它具有任何重要性,我的对象有一个"org.scala-lang" % "scala-library" % "2.12.4"而不是def main。不确定这是否重要......

1 个答案:

答案 0 :(得分:0)

答案最终与build.sbt一致。我在this stackoverflow post找到了答案。我不得不添加

mainClass in assembly := Some("NameOfMyMainClass")

进入build.sbt

之后,我做了

sbt clean assembly

并且能够同时运行java -jar target/.../my-fat-jar.jarscala target/.../my-fat-jar.jar

向@laughedelic致敬,指出我应该使用java -jar,并回答关于sbt compile src/...的问题:')