当前位置: 首页 > 知识库问答 >
问题:

Nashorn,为多个作用域编译一次,比如Rhino

吴镜
2023-03-14

我正在调查是否有可能将一个基于rhino的大型项目转移到纳肖恩。也就是说,该项目在一个rhino编译的脚本(10万行javascript)中运行了数千个作用域(~实例)。

我知道怎么做:

  • 多个nashorn引擎将为我提供多个/独立的范围。工作正常,但会消耗太多内存(1000个引擎…)

我可以用Rhino做什么,想用Nashorn做什么:

String SOURCE = "var i = 0; function add(a) { i += a; return i; }";
System.out.println("=== RHINO ===");
Context cx = Context.enter();
cx.setOptimizationLevel(Context.FEATURE_STRICT_EVAL); // optimization level 9

Script script = cx.compileString(SOURCE, "mySource", 1, null); // compile once

Scriptable scope1 = cx.initStandardObjects(); // 1st re-use
Scriptable scope2 = cx.initStandardObjects(); // 2nd re-use

script.exec(cx, scope1);
script.exec(cx, scope2);

Function add1 = (Function) scope1.get("add", scope1);
Function add2 = (Function) scope2.get("add", scope2);

try {
    Object r1 = add1.call(cx, scope1, scope1, new Object[]{6});
    System.out.println("result1=" + r1); // print 6
    r1 = add1.call(cx, scope1, scope1, new Object[]{4});
    System.out.println("result1=" + r1); // print 10
} catch (Exception ex) {
    ex.printStackTrace();
}

try {
    Object r2 = add2.call(cx, scope2, scope2, new Object[]{9});
    System.out.println("result2=" + r2); // prints 9
    r2 = add2.call(cx, scope2, scope2, new Object[]{3});
    System.out.println("result2=" + r2); // prints 12
} catch (Exception ex) {
    ex.printStackTrace();
}

Context.exit();

在上面的示例中,我编译了一次脚本,并使用多个作用域来隔离不同的执行实例。我怎么能对纳肖恩做这样的事?请记住,在我的实际项目中,我希望调用更复杂的函数,这些函数将在参数中包含javascript或java实例。

提前感谢您的帮助。

共有1个答案

弓磊
2023-03-14

Nashorn支持loadWithNewGlobal原语(https://wiki.openjdk.java.net/display/Nashorn/Nashorn扩展名#Nashornextensions loadWithNewGlobal)。该原语允许您在新的全局范围内加载脚本——每个脚本都有自己的“对象”、“函数”等定义。这似乎对您的用例有所帮助。还有范围间对象方法/属性访问支持。i、 例如,您可以在不同范围内评估的脚本之间传递和返回对象——适当的包装/镜像由Nashorn负责。

 类似资料:
  • 对Nashorn中的ENGINE_作用域和GLOBAL_作用域绑定有点困惑,尝试跟随这里的讨论。 在阅读本文之前,我对作用域(至少在rhino中)的理解是,全局_作用域中有一个单独的共享绑定,引擎_作用域中有每个单独引擎的单独绑定。然而,这一页似乎在说,每个引擎都将基本的javascript结构存储在存在于engines engine_范围(混淆地称为“Nashorn全局范围”)中的绑定中。这听起

  • 如果以下代码在多线程应用程序中可以工作,您可以帮助我吗。 这是我的Java脚本,将由Nashorn评估 这就是我创建脚本引擎的方式 在使用Testng进行测试时,此操作不会出现任何错误 测试结果1-请注意,有些数据是重复的 但是,如果我添加"并行=true"到@DataProvider我的脚本开始失败 测试结果2-请注意,重复一些数据,以表明相同的参考编号可能在测试过程中随机失败 有人可以确认我是

  • 我有一个带有多个模块和子模块的Maven项目,我想一次编译它,即只使用一个调用“MVN clean install”。 对于一个基本项目,以下结构将起作用: 超级POM: 模块A的POM: 模块B类似。 根POM为: Lib1 pom: 并且,例如模块A1 POM: 我需要首先构建超级POM: 只有到那时,它才会编译: 如果没有这种两步编译,您将如何构造项目以使其工作?

  • 问题内容: 我有这个,在设定的总数时我得到一个错误。为什么我不能多次访问CTE? 问题答案: A基本上是一次性视图。它只保留一个语句,然后自动消失。 您的选择包括: 重新定义第二次。从定义的末尾到您的之前,这就像复制粘贴一样简单。 将结果放入表格或变量中 将结果具体化为真实表并引用 稍微更改一下即可,只需从您的CTE: 。

  • 问题内容: 我通过JSR 223使用Nashorn来执行用户输入脚本的小片段: 不同的用户脚本会调用在静态中央库(在上面的代码片段的String中保留)中定义的JavaScript函数。 每次我想获得可以从Java调用的an时,我总是不得不重新编译大型库代码。 有什么方法可以将以前编译的代码与新代码结合在一起? 问题答案: 这是由JSR-223设计的;后面真的没有代码缓存。嗯,从 理论上讲 可以,

  • 有没有办法使用$watch订阅多个对象上的事件 E、 g。