Gradle构建GraalVM JS嵌入应用Uber Jar遇版本兼容问题
Gradle打包GraalVM JS Uber Jar版本兼容问题解决
问题分析
报错显示Polyglot版本24.0.1与Truffle版本23.1.1不兼容,核心原因是打包Uber Jar时,依赖解析引入了不一致的GraalVM相关组件版本——直接运行gradle run时依赖是正确的,但打包过程中混入了旧版本的Truffle依赖,或者重复的版本元数据文件导致加载错误。
解决方案
1. 强制统一所有GraalVM相关依赖版本
在build.gradle.kts中添加依赖约束,确保所有GraalVM组件(包括隐式引入的Truffle)都使用指定的24.0.1版本:
dependencies { implementation("org.graalvm.polyglot:polyglot:$graalVMVersion") implementation("org.graalvm.polyglot:js:$graalVMVersion") // 显式声明Truffle API版本,避免传递依赖引入旧版本 implementation("org.graalvm.truffle:truffle-api:$graalVMVersion") // 强制约束所有相关依赖版本一致 constraints { listOf( "org.graalvm.truffle:truffle-api", "org.graalvm.truffle:truffle-js", "org.graalvm.sdk:graal-sdk" ).forEach { dep -> implementation(dep) { version { strictly(graalVMVersion) } } } } testImplementation("junit:junit:4.13.2") }
2. 升级ShadowJar插件版本
旧版本ShadowJar(7.1.2)对Java 21的支持可能存在问题,升级到最新稳定版:
plugins { id("java") id("application") id("com.github.johnrengelman.shadow") version "8.1.1" }
3. 优化ShadowJar打包配置
调整打包逻辑,处理重复的元数据文件,确保只保留正确版本的资源:
tasks { withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> { archiveClassifier.set("") manifest { attributes(mapOf("Main-Class" to "org.example.embedding.Main")) } // 合并服务文件,避免GraalVM组件加载失败 mergeServiceFiles() // 排除重复的版本元数据文件,保留最新版本 duplicatesStrategy = DuplicatesStrategy.EXCLUDE exclude("META-INF/truffle-version.properties") exclude("META-INF/graalvm-version.properties") } // 保留原有任务依赖配置 build { dependsOn(shadowJar) } distZip { dependsOn(shadowJar) } distTar { dependsOn(shadowJar) } startScripts { dependsOn(shadowJar) } named("startShadowScripts") { dependsOn(named("jar")) } }
4. 验证依赖树
执行以下命令检查依赖树,确认所有GraalVM相关依赖版本均为24.0.1:
./gradlew dependencies --configuration runtimeClasspath | grep -E "(polyglot|truffle|graal)"
修改后的完整build.gradle.kts示例
plugins { id("java") id("application") id("com.github.johnrengelman.shadow") version "8.1.1" } java { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 } repositories { mavenCentral() gradlePluginPortal() } group = "org.example" version = "1.0-SNAPSHOT" description = "embedding" val graalVMVersion = "24.0.1" dependencies { implementation("org.graalvm.polyglot:polyglot:$graalVMVersion") implementation("org.graalvm.polyglot:js:$graalVMVersion") implementation("org.graalvm.truffle:truffle-api:$graalVMVersion") constraints { listOf( "org.graalvm.truffle:truffle-api", "org.graalvm.truffle:truffle-js", "org.graalvm.sdk:graal-sdk" ).forEach { dep -> implementation(dep) { version { strictly(graalVMVersion) } } } } testImplementation("junit:junit:4.13.2") } application { mainClass.set("org.example.embedding.Main") } tasks.withType<Test> { useJUnit() } tasks { withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> { archiveClassifier.set("") manifest { attributes(mapOf("Main-Class" to "org.example.embedding.Main")) } mergeServiceFiles() duplicatesStrategy = DuplicatesStrategy.EXCLUDE exclude("META-INF/truffle-version.properties") exclude("META-INF/graalvm-version.properties") } build { dependsOn(shadowJar) } distZip { dependsOn(shadowJar) } distTar { dependsOn(shadowJar) } startScripts { dependsOn(shadowJar) } named("startShadowScripts") { dependsOn(named("jar")) } }
执行./gradlew clean shadowJar重新打包后,运行Uber Jar即可正常启动。
内容的提问来源于stack exchange,提问作者Jonathan R
相关产品推荐
相关产品推荐

