Rhino 和并发访问 javax.script.ScriptEngine

2022-09-03 02:55:17

我通过API使用Rhino 1.6r2。我知道 Rhino 引擎声称自己是多线程的:“引擎实现在内部是线程安全的,脚本可以同时执行,尽管脚本执行对一个线程的影响可能对其他线程上的脚本可见。javax.script

我想知道的是,在什么确切的条件下,一个脚本执行的效果对另一个脚本执行是可见的?在我的代码中,我有时会重用一个对象,但是对于每次执行,我都会创建一个新的对象并将其传递给 。通过这种安排,内部状态有没有办法从一个执行泄漏到另一个执行?如果是这样,如何?ScriptEngineSimpleBindingseval(String, Bindings)

这里有一个非常翔实的答案,但它并没有完全告诉我我需要知道什么。


答案 1

javax.script 包是线程安全的,但如果您的脚本不是,则可能会遇到并发问题。脚本中的全局变量对所有线程都可见。因此,避免在 javascript 函数中使用全局变量

我现在遇到了这个问题。我的javascript如下:

function run(){
    regex = 0;
    regex += 1;
    return regex;
}

我在 ThreadPool(4) 中运行它 10.000 次,并打印结果。

for (int i = 0; i <= 10000; i++){
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Double result = (Double) invocable.invokeFunction("run");
                    System.out.println(result);
                } catch (Exception e) {}
            }
        });
    }

这是输出的一部分:

1.0
2.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
2.0
1.0
1.0
0.0

答案 2

是的,JSR223 没有指定脚本语言中的变量应如何与 given 绑定。因此,实现者完全有可能选择在引擎实例中存储全局范围变量,并在评估脚本时给出不同的参数来重用它。BindingsBindings

例如,JRuby 的 JSR223 绑定有一种模式以这种方式工作

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

public class Jsr223Binding {


    private Jsr223Binding() throws ScriptException {
        System.setProperty("org.jruby.embed.localvariable.behavior", "transient");
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("jruby");
        ScriptContext ctx1 = new SimpleScriptContext();
        ScriptContext ctx2 = new SimpleScriptContext();
        engine.eval("$foo = 5\nputs $foo", ctx1);
        engine.eval("puts $foo", ctx2);
    }

    public static void main(String[] args) throws ScriptException {
        new Jsr223Binding();
    }
}