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

JS脚本在Java 8运行正常,Java 11下通过Nashorn引擎执行报错

错误成因
  • 模块系统的内部API限制:Java 9引入JPMS模块系统后,JDK默认封装了所有非公开的内部API,你报错中提到的NODE_PATH属于Nashorn的内部运行时属性,Java 8中可随意访问,Java 11中默认禁止未授权的内部属性/方法访问,直接调用就会触发unknown call type错误。
  • Nashorn自身行为变更:Java 11自带的Nashorn版本收紧了全局作用域修改权限、CommonJS require 实现逻辑和内部节点访问规则,Java 8中可正常运行的隐式全局对象挂载、内部属性读取逻辑在新版本中不再被支持。
  • 编译优化逻辑差异:Java 11的Nashorn即时重编译机制更严格,当检测到脚本访问未公开的内部成员时,会直接抛出类型不识别错误,而Java 8版本会做兼容降级处理。
适配解决方案
  • 添加JVM启动参数放开模块限制:在Java进程启动时添加以下参数,开放Nashorn内部模块的访问权限:
    --add-exports jdk.scripting.nashorn/jdk.nashorn.internal.runtime=ALL-UNNAMED
    --add-opens jdk.scripting.nashorn/jdk.nashorn.internal.runtime=ALL-UNNAMED
    
    如果脚本还用到其他Nashorn内部包,按照上述格式补充对应的导出/开放参数即可。
  • 修改JS代码规避内部属性访问:移除脚本中所有直接访问NODE_PATH等Nashorn内部属性的逻辑,如果需要获取脚本路径等信息,改为在Java层调用__toCall方法时作为参数主动传入,不要依赖Nashorn内部属性读取。
  • 显式创建兼容模式的Nashorn引擎:不要直接通过ScriptEngineManager获取默认引擎,改用NashornScriptEngineFactory指定兼容参数创建引擎,适配Java 8的行为:
    NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
    // 开启ES6支持、脚本模式,关闭Java严格访问限制
    ScriptEngine engine = factory.getEngine(new String[]{"--language=es6", "-scripting", "--no-java-strict"});
    
  • 主动绑定全局对象:脚本中用到的StringLeaf、Structure、test、vc等全局对象,不要依赖Nashorn隐式挂载,改为在Java层主动绑定到引擎上下文:
    engine.put("StringLeaf", 你的StringLeaf实现对象);
    engine.put("Structure", 你的Structure实现对象);
    engine.put("test", 你的test实例);
    engine.put("vc", 你的vc实例);
    
  • 使用独立版本的Nashorn依赖:如果上述方案都无法解决,可以移除JDK自带的Nashorn依赖,引入开源独立维护的Nashorn版本,不受JDK模块系统限制,完全兼容Java 8的行为,Maven依赖配置如下:
    <dependency>
        <groupId>org.openjdk.nashorn</groupId>
        <artifactId>nashorn-core</artifactId>
        <version>15.4</version>
    </dependency>
    

内容的提问来源于stack exchange,提问作者yurii.pitomets

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 15:54:05