Scala:运行fat jar时找不到主类

Posted

技术标签:

【中文标题】Scala:运行fat jar时找不到主类【英文标题】:Scala: Could not find main class when running fat jar 【发布时间】:2020-07-28 16:32:27 【问题描述】:

在我的小 Scala 项目中添加了两个依赖项后,我最近遇到了一些问题。我无法再运行我的项目。 Error: Could not find or load main class a.b.c.DataExtractor。我已经花了一整天的时间寻找类似的问题,因为同样的错误出现在其他平台上的很多帖子中。

我的胖罐是用 sbt 程序集创建的。


Seq(
  "org.apache.httpcomponents" % "httpclient" % "4.5.12",
  "org.apache.httpcomponents" % "httpmime" % "4.5.12",
  "org.apache.olingo" % "olingo-odata2-api" % "2.0.11",
  "org.apache.olingo" % "olingo-odata2-core" % "2.0.11",
  "com.azure" % "azure-security-keyvault-secrets" % "4.1.0",
  "com.azure" % "azure-identity" % "1.0.5",
  "org.slf4j" % "slf4j-api" % "1.7.30"
  )

一旦我添加了 com.azure 依赖项,它们就会附带更多的依赖项,我无法再启动我的项目。

在我的 target/scala-2.11 文件夹中,我有两个需要的 jar:

data-extractor-assembly-0.1.0-SNAPSHOT.jar scala-library-2.11.12.jar

为了启动应用程序,我运行以下命令 java -cp data-extractor-assembly-0.1.0-SNAPSHOT.jar:scala-library-2.11.12.jar -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG -verbose a.b.c.DataExtractor

我的猜测是它与程序集的构建有关。我检查了生成的工件,MANIFEST.MF 文件按预期显示Main-Class: a.b.c.DataExtractor,但仍有一些问题。我就是不知道问题的根源是什么。

那么,Scala 2.11.12、sbt 1.2.8 和 Java 1.8.0_162,如果相关的话

任何信息或提示将不胜感激。谢谢。

【问题讨论】:

主类是否也在 JAR 中?也许冲突解决使您最终得到了一个以不同名称具有 main 的库版本? @MateuszKubuszok 不,主要课程是我自己的。它在生成的胖罐中具有正确的名称,包含包和所有内容。我什至反编译它并将其与“简单的 fat-jar”进行比较,后者不依赖于 Azure 项目。同样的事情,同样的代码,同样的 MANIFEST.MF 文件。看不出问题的原因 另一个想到的是加载过程中的错误。试着让你的主类基本上是空的,这样就不需要从类加载器加载其他东西了。检查是否仍然出现错误。 @MateuszKubuszok 感谢您迄今为止的建议以及您对此问题的兴趣。经过一番努力,我确实设法解决了它。请查看我发布的答案以了解更多信息 【参考方案1】:

最后我确实设法通过 build.sbt 文件中的一些 sbt 汇编魔法解决了这个问题。我还包括了 scala 库文件,所以我只需要为 -cp 参数指定 fat-jar。

assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = true),
assemblyMergeStrategy in assembly := 
  case PathList("javax", "activation", xs @ _*)     => MergeStrategy.last
  case "about.html"                                 => MergeStrategy.rename
  case "plugin.properties"                          => MergeStrategy.last
  case "log4j.properties"                           => MergeStrategy.last
  case "module-info.class" => MergeStrategy.discard
  case PathList("META-INF", xs @ _*) =>
    xs match 
      case ("MANIFEST.MF" :: Nil) => MergeStrategy.discard
      // Concatenate everything in the services directory to keep GeoTools happy.
      case "mailcap" :: Nil => MergeStrategy.last
      case "mimetypes.default" :: Nil => MergeStrategy.last

      case ("services" :: _ :: Nil) =>
        MergeStrategy.concat
      // Concatenate these to keep JAI happy.
      case "javax.media.jai.registryFile.jai" :: Nil | "registryFile.jai" :: Nil |
           "registryFile.jaiext" :: Nil =>
        MergeStrategy.concat
      case name :: Nil => 
        // Must exclude META-INF/*.([RD]SA|SF) to avoid "Invalid signature file digest for Manifest main attributes" exception.
        if (name.endsWith(".RSA") || name.endsWith(".DSA") || name.endsWith(".SF"))
          MergeStrategy.discard
        else
          MergeStrategy.first
      
      case _ => MergeStrategy.first
    
  case x =>
    val oldStrategy = (assemblyMergeStrategy in assembly).value
    oldStrategy(x)

【讨论】:

以上是关于Scala:运行fat jar时找不到主类的主要内容,如果未能解决你的问题,请参考以下文章

java运行时找不到主类

java运行显示“找不到或无法加载主类”怎么回事?

运行java文件显示找不到或无法加载主类怎么解决?

运行程序时找不到主类

java运行显示“找不到或无法加载主类”!

java运行显示“找不到或无法加载主类”!