【问题标题】:readFully not defined with Java Nashorn Javascript EnginereadFully 未使用 Java Nashorn Javascript 引擎定义
【发布时间】:2015-03-03 12:17:03
【问题描述】:

我正在尝试使用新的 Java 8 Nashorn javascript 引擎运行 javascript 脚本,但它失败并出现以下错误:

<eval>:1 ReferenceError: "readFully" is not defined

该脚本使用应该在全局范围内定义的 readFully 函数 nashorn 在启用脚本模式的情况下运行(这是通过 ScriptEngine 运行时的默认设置,如此处 http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-December/002562.html 所示)。

这是一个重现错误的示例:

import java.io.FileNotFoundException;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Test {

    public static void main(String[] argv) throws FileNotFoundException, ScriptException {
        ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");

        scriptEngine.eval("print('Hey!');print(print);print(readFully);");


    }
}

此示例打印 Hey !然后是 print 函数的源代码(另一个 nashorn 内置函数),最后它应该打印 readFully 方法的源代码。但我有这个例外:

Exception in thread "main" javax.script.ScriptException: ReferenceError: "readFully" is not defined in <eval> at line number 1
    at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:586)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:570)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:525)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:521)
    at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:192)
    at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
    at com.github.bringking.maven.requirejs.Test.main(Test.java:14)
Caused by: <eval>:1 ReferenceError: "readFully" is not defined
    at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:58)
    at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:320)
    at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:292)
    at jdk.nashorn.api.scripting.NashornScriptEngine.__noSuchProperty__(NashornScriptEngine.java:272)
    at jdk.nashorn.internal.scripts.Script$engine.L:35(nashorn:engine/resources/engine.js:37)
    at jdk.nashorn.internal.scripts.Script$\^eval\_.runScript(<eval>:1)
    at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:535)
    at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:209)
    at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
    at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:568)
    ... 5 more

当示例脚本使用带有 -scripting 参数的 nashorn 命令行运行时(使用 jdk 的 jjs 工具),一切都很好。这是同一脚本的结果:

Hey!
function print() { [native code] }
function readFully() { [native code] }

我可以重写一个 readFully 方法并将其与脚本上下文绑定,但我更愿意了解它为什么不起作用并使用已经内置的函数。

问候

【问题讨论】:

  • 您使用的是什么 JDK? Oracle 还是 OpenJDK?
  • Windows 7 上的 Orcale JDK:java 版本“1.8.0_25”,Java(TM) SE 运行时环境(构建 1.8.0_25-b18),Java HotSpot(TM) 客户端 VM(构建 25.25-b02 , 混合模式)
  • 您链接到的博文是 re: openjdk。它们仍然有些不同。
  • 确实如此。 1分。所以,现在我正在寻找一种以编程方式“强制”Nashorn 脚本模式的方法 :)
  • 不确定。但是你的引擎应该是javascript(不是nashorn)---如果他们在Java 9中重命名它呢?

标签: java javascript nashorn


【解决方案1】:

最后,我实现了一个我在脚本中使用的 readFully 函数(仅与 Nashorn 兼容):

function readFully(url) {
    var result = "";
    var imports = new JavaImporter(java.net, java.lang, java.io);

    with (imports) {

        var urlObj = null;

        try {
            urlObj = new URL(url);
        } catch (e) {
            // If the URL cannot be built, assume it is a file path.
            urlObj = new URL(new File(url).toURI().toURL());
        }

        var reader = new BufferedReader(new InputStreamReader(urlObj.openStream()));

        var line = reader.readLine();
        while (line != null) {
            result += line + "\n";
            line = reader.readLine();
        }

        reader.close();
    }

    return result;
}

【讨论】:

    【解决方案2】:

    readFully 不是标准的 JavaScript 函数,它在 Nashorn 中也可能不是标准的。

    similar issues 当 Rhino 被选中包含在 Java 6 的 Sun 实现中时。脚本工具可能会提供嵌入式 API 中不存在的增强功能。 readFully 不是 Java 8 Nashorn API 中记录的函数。

    在 Java 的早期版本中,规范声明提供的脚本引擎是 JRE 供应商的实现细节。我不知道 Java 8 是否对强制提供的引擎做出任何规定,或者它是否做出任何未来的兼容性保证。如果这可能是一个问题,我会彻底检查JSR-337。

    【讨论】:

    • 感谢您的信息。我将自己实现一个 readFully 函数。
    【解决方案3】:

    https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions

    readFully(仅限-脚本模式)

    此函数读取作为字符串参数传入的文件的全部内容并将其发送到标准输出,或者您可以将结果分配给变量。

    readFully 示例:

    jjs> readFully("text.txt") This is the contents of the text.txt file located in the current working directory.

    【讨论】:

    • 我的问题是通过 ScriptEngine API 运行时未定义 readFully。不适用于 jjs 可执行文件(这样,一切都很好)。
    • 您可以使用直接的 nashorn 接口 NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); 将选项传递给 Nashorn String[] options = new String[] { "—脚本" }; NashornScriptEngine 引擎 = factory.getScriptEngine(options);或者简单地将“#”作为脚本的第一个字符。
    【解决方案4】:

    readFully 仅在脚本模式下启用。 Nashorn docs

    试试这个:

    >>jjs -scripting
    jjs> readFully("your_file")
    

    【讨论】:

      【解决方案5】:

      当您在应用程序中启用脚本时,readFully() 函数仅在 nashorgn 中作为内置函数可用 有两种方法可以做到这一点:-

      1. 在运行应用程序以启用 nashorn 时传递 -Dnashorn.args=-scripting 脚本
      2. 通过使用脚本参数创建 Nashorn 引擎以编程方式启用它
        NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
        ScriptEngine engine = factory.getScriptEngine(new String[] { "-scripting" });
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-09
        • 1970-01-01
        • 2019-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-19
        相关资源
        最近更新 更多