SpringBoot应用中GraalVM JavaScript引擎FileSystemNotFoundException问题
问题
我创建了SpringBoot项目,通过在pom.xml中添加GraalVM依赖执行JavaScript代码,依赖配置如下:
<dependency> <groupId>org.graalvm.js</groupId> <artifactId>js</artifactId> <version>1.0.0-rc10</version> </dependency> <dependency> <groupId>org.graalvm.js</groupId> <artifactId>js-scriptengine</artifactId> <version>1.0.0-rc10</version> </dependency> <dependency> <groupId>org.graalvm.truffle</groupId> <artifactId>truffle-api</artifactId> <version>1.0.0-rc10</version> </dependency>
同时编写了执行JavaScript的方法:
public String transformJson(String transformationFunction, String payload) { Context context = Context.create(); if (transformationFunction == null || transformationFunction.isEmpty()) transformationFunction = "(function transform(payload) {\n" + " return payload; \n" + "})"; else transformationFunction = "(" + transformationFunction + ")"; Value eval = context.eval("js", transformationFunction); return eval.execute(payload).asString(); }
这段代码在本地运行正常,但部署到AWS后抛出FileSystemNotFoundException异常,异常栈如下:
java.nio.file.FileSystemNotFoundException: null at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:156) at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:142) at java.base/java.nio.file.Path.of(Path.java:208) at java.base/java.nio.file.Paths.get(Paths.java:98) at com.oracle.truffle.polyglot.LanguageCache.collectLanguages(LanguageCache.java:284) at com.oracle.truffle.polyglot.LanguageCache.createLanguages(LanguageCache.java:211) at com.oracle.truffle.polyglot.LanguageCache.languages(LanguageCache.java:201) at com.oracle.truffle.polyglot.PolyglotEngineImpl.initializeLanguages(PolyglotEngineImpl.java:486) at com.oracle.truffle.polyglot.PolyglotEngineImpl.<init>(PolyglotEngineImpl.java:174) at com.oracle.truffle.polyglot.PolyglotEngineImpl.<init>(PolyglotEngineImpl.java:158) at com.oracle.truffle.polyglot.PolyglotImpl.buildEngine(PolyglotImpl.java:197) at org.graalvm.polyglot.Engine$Builder.build(Engine.java:488) at org.graalvm.polyglot.Context$Builder.build(Context.java:1085) at org.graalvm.polyglot.Context.create(Context.java:663) at com.infy.supplier.erp.service.impl.JavascriptEngineServiceImpl.transformJson(JavascriptEngineServiceImpl.java:17) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) at com.infy.supplier.erp.aop.logging.LoggingAspect.logAround(LoggingAspect.java:105) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568)
经调研,该异常可能因无法找到语言配置文件导致,需在系统环境变量中明确指定,但本地未配置却能正常运行,且找不到GraalVM的特定语言配置文件,请问如何解决该错误?
解决方案
1. 升级GraalVM依赖版本
当前使用的1.0.0-rc10是老旧的预览版本,存在大量类路径和文件系统处理的兼容性问题。建议升级到最新稳定版本(如22.3.x或更高),新版本修复了云环境、容器化场景下的诸多问题。
修改pom.xml中的依赖版本:
<dependency> <groupId>org.graalvm.js</groupId> <artifactId>js</artifactId> <version>22.3.2</version> </dependency> <dependency> <groupId>org.graalvm.js</groupId> <artifactId>js-scriptengine</artifactId> <version>22.3.2</version> </dependency> <dependency> <groupId>org.graalvm.truffle</groupId> <artifactId>truffle-api</artifactId> <version>22.3.2</version> </dependency>
2. 显式指定JavaScript语言并禁用自动探测
创建Context时,明确指定只加载JavaScript语言,避免GraalVM扫描所有可能的语言配置文件,绕过文件系统访问问题:
public String transformJson(String transformationFunction, String payload) { // 显式配置仅加载JavaScript,禁用自动语言探测 Context context = Context.newBuilder("js") .allowAllAccess(true) // 生产环境建议根据需求调整最小权限 .build(); if (transformationFunction == null || transformationFunction.isEmpty()) transformationFunction = "(function transform(payload) {\n" + " return payload; \n" + "})"; else transformationFunction = "(" + transformationFunction + ")"; Value eval = context.eval("js", transformationFunction); return eval.execute(payload).asString(); }
3. 添加JVM启动参数跳过语言缓存扫描
在应用启动时添加以下JVM参数,强制GraalVM跳过语言缓存的文件系统扫描:
-Dpolyglot.engine.WarnInterpreterOnly=false -Dpolyglot.language.js.ECMAScript=latest -Dtruffle.class.path.append=./target/classes
如果是在AWS Elastic Beanstalk或ECS中部署,可将这些参数添加到应用的启动配置中。
4. 检查部署包的类路径完整性
确保部署包(如jar包)中包含GraalVM的所有依赖资源,尤其是META-INF/truffle/language下的语言配置文件。解压部署包检查,确认存在org.graalvm.js.json文件:
META-INF/truffle/language/org.graalvm.js.json
如果缺失,需调整Maven打包配置,避免排除这些资源文件。
内容的提问来源于stack exchange,提问作者Anmol Jain
相关产品推荐
相关产品推荐

