GraalJS打包为可运行jar包后无法构建ScriptEngine问题求助
问题解决方案
根因定位
你遇到的问题本质是libGDX默认的fatJar打包逻辑存在服务注册文件合并冲突:
GraalVM系列组件依赖Java SPI机制注册语言实现,所有语言的注册信息都存放在各依赖jar包的META-INF/services/org.graalvm.polyglot.LanguageProvider路径下。libGDX的desktop:dist任务默认不会合并同名SPI配置文件,只会保留最后一个加载的jar包对应的配置,导致GraalJS的语言注册信息被覆盖,运行时无法识别js语言。
解决方案
- 第一步:修改desktop模块的build.gradle打包配置,添加SPI服务文件合并规则
在desktop模块的build.gradle中找到jar任务配置,添加mergeServiceFiles()配置,示例如下:
jar { // 原有配置保留,添加如下内容 mergeServiceFiles() // 可选:排除存在冲突的重复非必要文件 exclude 'META-INF/*.DSA' exclude 'META-INF/*.RSA' exclude 'META-INF/*.SF' }
如果你的项目用的是shadowJar插件打包,对应配置如下:
shadowJar { mergeServiceFiles() }
- 第二步:显式指定Graal Context的类加载器
修改ScriptEngine构建代码,在Context构建时显式传入上下文类加载器,避免打包后类加载器异常:
private fun getGraalEngine() = GraalJSScriptEngine.create( Engine.newBuilder() .allowExperimentalOptions(false) .useSystemProperties(false) .build(), Context.newBuilder("js") .allowHostAccess(HostAccess.ALL) .allowHostClassLookup { true } .allowAllAccess(true) // 新增行:指定当前线程上下文类加载器 .serverClassLoader(Thread.currentThread().contextClassLoader) )
- 第三步:打包后验证
导出jar包后,解压检查META-INF/services/org.graalvm.polyglot.LanguageProvider文件,确认存在org.graalvm.js.lang.JsLanguageProvider条目即可。
内容的提问来源于stack exchange,提问作者Mihai Fumarel
相关产品推荐
相关产品推荐

