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

Java 11下独立版Nashorn调用eval抛出StackOverflowError问题

Nashorn长表达式eval在Java11环境栈溢出问题修复

问题背景

  • 异常现象:对较长逻辑表达式执行eval求值时,Java 8环境运行正常,Java 11环境抛出java.lang.StackOverflowError,错误堆栈定位到org.openjdk.nashorn.internal.codegen.LocalVariableTypesCalculator的二元节点处理逻辑
  • 已尝试的修复操作:
    • 搭建Maven项目,引入15.3版本org.openjdk.nashorn:nashorn-core依赖,配置maven-compiler-plugin指定编译目标为Java 11,搭配maven-dependency-plugin、maven-jar-plugin打包为可执行Jar
    • 代码层面放弃通过javax.script.ScriptEngineManager获取引擎,改为直接实例化org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory获取脚本引擎,期望加载独立版Nashorn规避内置版本缺陷
    • 尝试添加JVM启动参数--module-path引入依赖包、--add-modules org.openjdk.nashorn加载独立模块
  • 验证结果:
    • 使用Java 11.0.9 LTS编译打包运行,引擎信息打印为OpenJDK Nashorn 15.3,但仍抛出相同栈溢出错误
    • 相同代码在移除内置Nashorn的Java 17环境运行无异常,确认Java 11环境实际仍加载了JDK内置Nashorn实现

根因

Java 11内置的Nashorn由引导类加载器加载,优先级高于classpath下的第三方依赖。即使直接实例化独立版的NashornScriptEngineFactory,其内部依赖的代码生成、字节码处理等内部工具类仍会被优先加载JDK内置版本,独立版中修复的递归栈溢出逻辑未实际生效。

修复方案(仅需Maven配置,无额外JVM参数要求)

通过maven-shade-plugin配置fatjar打包规则,将独立版Nashorn的类优先打入Jar包根路径,覆盖JDK内置类的加载优先级:

  1. 移除原有maven-jar-plugin、maven-dependency-plugin组合的fatjar打包配置,替换为maven-shade-plugin配置:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.5.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <!-- 替换为自身项目的主类全限定名 -->
                        <mainClass>com.example.YourMainClass</mainClass>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                </transformers>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                        </excludes>
                    </filter>
                </filters>
            </configuration>
        </execution>
    </executions>
</plugin>
  1. 保留原有maven-compiler-plugin的Java 11编译配置,nashorn-core依赖保持默认compile作用域即可:
<dependency>
    <groupId>org.openjdk.nashorn</groupId>
    <artifactId>nashorn-core</artifactId>
    <version>15.3</version>
</dependency>
  1. 代码层无需修改原有直接实例化NashornScriptEngineFactory的逻辑,执行mvn clean package生成可执行Jar后,直接通过java -jar 生成的jar包名.jar启动即可。

验证方式

启动后可通过断点或日志打印LocalVariableTypesCalculator类的加载路径,确认该类来自Jar包内的独立版Nashorn而非JDK内置路径,再执行长逻辑表达式eval操作即可确认栈溢出问题已修复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:03:19