You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jpackage打包Kotlin-Compose-Spring应用时主类找不到问题求助

问题分析与解决方案

问题描述

开发Kotlin-Compose-Spring独立应用,为Windows平台制作带JRE的安装包,但使用jpackage打包后,运行Jar或Exe时出现主类找不到错误:

Error: Could not find or load main class com.tfra.mechanic_management.MechanicManagementApplicationKt
Caused by: java.lang.ClassNotFoundException: com.tfra.mechanic_management.MechanicManagementApplicationKt

同时生成的Exe本地无法正常运行,仅能在Windows Sandbox执行,否则需通过任务管理器终止。

错误原因及修复步骤

1. BootJar任务配置错误

Spring Boot的bootJar默认已生成包含所有依赖的可执行Fat Jar,你手动添加runtimeClasspath依赖的逻辑会导致Jar结构混乱,主类无法被正确识别。

修改BootJar任务配置:

tasks.named<org.springframework.boot.gradle.tasks.bundling.BootJar>("bootJar") {
    archiveFileName.set("${appName}-${version}.jar")

    manifest {
        attributes["Main-Class"] = "com.tfra.mechanic_management.MechanicManagementApplicationKt"
    }

    // 移除手动打包依赖的代码,bootJar已自动处理依赖打包
}

2. jlink生成Runtime Image时的模块路径错误

你将build/libs加入jlink的module-path,但Spring Boot应用是非模块化的,这会导致Runtime Image引入不必要的内容,甚至缺少必要模块。

修改generateRuntimeImage任务:

tasks.register<Exec>("generateRuntimeImage") {
    group = "build"
    description = "Generates a custom runtime image"

    val runtimeDir = layout.buildDirectory.dir("my-runtime").get().asFile

    doFirst {
        if (runtimeDir.exists()) {
            runtimeDir.deleteRecursively()
        }
    }

    commandLine(
        "jlink",
        "--module-path", "${System.getProperty("java.home")}/jmods",
        "--add-modules", "java.base,java.desktop,java.sql,java.naming,java.logging,java.management",
        "--output", runtimeDir.absolutePath,
        "--strip-debug",
        "--no-man-pages",
        "--no-header-files"
    )
}

3. jpackage的main-jar参数错误

--input已指定为build/libs,--main-jar只需填写Jar文件名,无需绝对路径,否则jpackage无法正确定位Jar内的主类。

修改createInstaller任务的commandLine部分:

commandLine(
    "$javaHome/bin/jpackage",
    "--type", "exe",
    "--input", "build/libs",
    "--main-jar", "${appName}-${version}.jar", // 仅填Jar文件名
    "--name", appName,
    "--main-class", "com.tfra.mechanic_management.MechanicManagementApplicationKt",
    "--dest", outputDir,
    "--app-version", version.toString(),
    "--icon", "src/main/resources/car_icon.ico",
    "--java-options", "-Djava.awt.headless=false",
    "--java-options", "-Dlogging.file=app.log",
    "--resource-dir", "src/main/resources",
    "--runtime-image", layout.buildDirectory.dir("my-runtime").get().asFile.absolutePath
)

4. 应用启动逻辑优化

Compose的application函数是阻塞式的,需确保Spring Boot上下文在关闭时正确销毁,避免进程残留导致假死:

修改主类启动代码:

@SpringBootApplication
@EnableJpaRepositories(basePackages = ["com.tfra.mechanic_management.repository.jpa"])
@EntityScan(basePackages = ["com.tfra.mechanic_management.repository.entity"])
@ComponentScan(basePackages = ["com.tfra"])
class MechanicManagementApplication

fun main(args: Array<String>) {
    val context = runApplication<MechanicManagementApplication>(*args)

    application {
        Window(
            onCloseRequest = {
                // 关闭Spring Boot上下文
                context.close()
                exitApplication()
            },
            title = "Mechanic Management"
        ) {
            MaterialTheme {
                AppUI(context)
            }
        }
    }
}

5. 验证Jar文件结构

打包后解压生成的Jar文件,确认com/tfra/mechanic_management/MechanicManagementApplicationKt.class存在,确保主类被正确编译打包。

额外注意事项

  • 确保使用Java 17的JDK执行jlink和jpackage,与项目toolchain版本一致
  • 检查本地Windows环境是否有其他Java进程或依赖冲突,可尝试清理build目录后重新打包

内容的提问来源于stack exchange,提问作者TechGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:04:55