Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 脚本引擎清除并处置_Java_Nashorn_Scriptengine - Fatal编程技术网

Java 脚本引擎清除并处置

Java 脚本引擎清除并处置,java,nashorn,scriptengine,Java,Nashorn,Scriptengine,我的应用程序使用ScriptEngine为最终用户提供插件功能 ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); 每当用户对其脚本进行更改时,应用程序就会用新实例替换引擎实例 String newScript = ...; engine = engineManager.getEngineByN

我的应用程序使用
ScriptEngine
为最终用户提供插件功能

ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
每当用户对其脚本进行更改时,应用程序就会用新实例替换引擎实例

String newScript = ...;
engine = engineManager.getEngineByName("nashorn");
engine.eval(newScript);
两个密切相关的问题:

  • 我是否应该尝试重用引擎并对其执行某种
    clear()

  • 如果我只是用一个新实例替换引擎,我是否应该以某种方式处理以前的实例,以避免内存泄漏?(例如,我可以想象用户可以创建一个启动线程的脚本。)


问题是,我找不到任何类似于
clear()
dispose()
的方法。这是否意味着我当前的方法是正确的?

您可以使用单个引擎实例,但可以使用单独的
绑定
对象<代码>绑定充当顶级程序环境,因此如果您想将脚本评估为基本上是“新的全局范围”,那么您可以这样做。查看
javax.script
,了解如何做到这一点。您可以使用
ScriptEngine.eval
作为第二个参数,或者使用
ScriptContext
作为第二个参数

即使没有脚本代码从之前的评估中幸存下来,也可以节省一些初始化时间,因为脚本引擎已经预定义了各种JavaScript数据持有者类和属性映射(“隐藏类”)


还有:是的,所有东西都是垃圾收集的。不需要显式的“处理”API。

我只想分享我自己测试的内容。这很有道理,但对于那些仍有疑问的人来说:如果只替换引擎实例,创建的线程确实会继续运行。

public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();

    String script =
            "new java.lang.Thread(function() {\n" +
            "  for(;;) {" +
            "    print('Here\\'s Johnny !');" +
            "    java.lang.Thread.sleep(1000);" +
            "  }\n" +
            "}).start();";

    ScriptEngine engine = manager.getEngineByName("nashorn");
    try {
        engine.eval(script);
    } catch (ScriptException e) {
        e.printStackTrace();
    }
    
    // replace engine
    engine = manager.getEngineByName("nashorn");
    engine.eval("print('please, make it stop!!!');");
    
    // please collect !!!
    System.gc();
}
输出:

Here's Johnny ! please, make it stop!!! Here's Johnny ! Here's Johnny ! Here's Johnny ! ... 但您也可以使用
类过滤器禁用特定类

    ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine((className) -> {
        if ("java.lang.Thread".equals(className)) return false;
        if ("java.lang.Runnable".equals(className)) return false;
        if ("java.util.Timer".equals(className)) return false;
        if (className.startsWith("java.util.concurrency")) return false;
        if (className.startsWith("javafx")) return false;
        if (className.startsWith("javax.swing")) return false;
        if (className.startsWith("java.awt")) return false;
        return true;
    });

注意:一旦定义了
类过滤器
,反射类也会被自动阻止。因此,您不必显式地阻止这些包。

一切都非常清楚,但是关于“无需处理”部分,请参见下面的回答:显然java不会为您清理正在运行的线程。
    ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine((className) -> {
        if ("java.lang.Thread".equals(className)) return false;
        if ("java.lang.Runnable".equals(className)) return false;
        if ("java.util.Timer".equals(className)) return false;
        if (className.startsWith("java.util.concurrency")) return false;
        if (className.startsWith("javafx")) return false;
        if (className.startsWith("javax.swing")) return false;
        if (className.startsWith("java.awt")) return false;
        return true;
    });