【问题标题】:compiling and running jars with scalac vs sbt?用scalac vs sbt编译和运行jar?
【发布时间】:2018-08-26 01:41:23
【问题描述】:

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

首先,我可以运行sbt assembly 并在/target/scala-2.12/ 中获得padsystem-assembly-0.0.1.jar。 (我必须创建一个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 compilesbt 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 目录并尝试运行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

为什么我可以成功sbt run 我的代码,但不能使用 scala 或 java 运行 jar,尤其是当所有依赖项都包含在 fat jar 中时?

当我执行scalac src/main/scala/OdinExtractor.scalasbt compile OdinExtractor.scala 时,为什么我的依赖关系会出错?第一个我猜是因为scalac 想要类似

scalac -cp "all:of:the:classpath:stuff:ever" OdinExtractor.scala.

(顺便说一句,我不知道该怎么做……)

据我所知,这就是我们使用sbt 开头的原因,是吗?为了避免混乱的类路径的东西。这让我想到了下一个问题:为什么当我将 sbt compile 指向特定文件时它会失败?当我从src/main/scala 目录运行它时,为什么它会失败?我不知道第一个问题,但我对第二个问题的猜测是sbt 必须始终从基本目录运行?

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

最后,我有一种奇怪的感觉,也许所有这一切都归结为 1)我对 classpaths 的困惑,或者 2)也许是我的项目结构?但是由于我的东西与sbt run一起运行,我完全不知所措......请帮忙!让我知道我是否需要在我的帖子中添加任何其他内容以使其更清楚。谢谢!

编辑 - 根据我的build.sbt,我确实包含了scala-library jar,以便它可以被Java 解析。 IE。 "org.scala-lang" % "scala-library" % "2.12.4"

另外,如果它有任何重要性,我的对象有一个def main 而不是extends App。不确定这是否重要...

【问题讨论】:

  • 将您的assembly.sbt 添加到问题中,这可能会有所帮助。使用 java 运行时,使用java -jar target/...java -cp target/... your.main.Class。并且sbt compile src/... 不会(不应该)处理单独的源文件。

标签: java scala sbt sbt-assembly


【解决方案1】:

答案最终是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/... 的问题:')

【讨论】:

    猜你喜欢
    • 2015-01-30
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2016-05-06
    • 2016-07-20
    相关资源
    最近更新 更多