sbt-assembly构建fat jar运行提示找不到主类该如何解决?
问题解决步骤
核心根因:当前合并策略将所有META-INF目录下的文件全部丢弃,其中包含了记录主类信息的MANIFEST.MF文件,导致java -jar命令无法识别jar包的主类配置,这是报错的核心原因。
步骤1:修正assembly合并策略
替换当前的全局assemblyMergeStrategy配置,不要全量丢弃META-INF下的所有文件,仅过滤冲突的签名、索引文件即可,同时建议将合并策略放到子项目的settings配置中,避免作用范围错误:
ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / organization := "com.gordon.timeshare.apps" ThisBuild / scalaVersion := "2.13.5" lazy val app = (project in file("app")) .settings( assembly / mainClass := Some("com.gordon.timeshare.apps.TimeShareLauncher"), assembly / assemblyJarName := "TimeShareLauncher.jar", assembly / assemblyMergeStrategy := { // 保留sbt自动生成的MANIFEST.MF,仅丢弃META-INF下冲突的签名、校验文件 case PathList("META-INF", xs @ _*) if xs.exists(f => f.endsWith(".SF") || f.endsWith(".DSA") || f.endsWith(".RSA") || f == "INDEX.LIST") => MergeStrategy.discard case x => MergeStrategy.first } )
步骤2:清理缓存重新构建
执行sbt clean assembly命令重新构建,构建前关闭占用项目target目录的进程(如IDE、文件资源管理器),解决构建时的目录已存在警告。
步骤3:验证jar包内容
构建完成后执行以下命令验证主类是否存在:jar tf TimeShareLauncher.jar | grep TimeShareLauncher
如果输出com/gordon/timeshare/apps/TimeShareLauncher.class则说明主类已正常打入jar包。
再执行命令验证MANIFEST.MF是否包含主类配置:jar xf TimeShareLauncher.jar META-INF/MANIFEST.MF && cat META-INF/MANIFEST.MF
确认文件中存在Main-Class: com.gordon.timeshare.apps.TimeShareLauncher配置项。
步骤4(可选):替换主类实现方式
如果上述操作后仍存在问题,可将extends App的实现替换为显式声明main方法,避免App trait的延迟加载特性导致类加载异常:
package com.gordon.timeshare.apps object TimeShareLauncher { def main(args: Array[String]): Unit = { // 原启动逻辑写在这里 } }
内容的提问来源于stack exchange,提问作者DanGordon
相关产品推荐
相关产品推荐

