Java 在执行过程中停止Rhino引擎

Java 在执行过程中停止Rhino引擎,java,rhino,Java,Rhino,Rhino引擎是否有一个api可以停止 脚本FIE在中间。例如,我有一个脚本文件,其中 有一个infinte循环。我怎么才能停止在中间执行呢? 当然,我可以停止启动Rhino引擎的jvm 超越剧本。但是我不想因为这个原因而终止整个jvm会话,因为我已经通过编程启动了脚本,Rhino引擎也在与我的应用程序相同的jvm中运行。Rhino引擎需要任何机制来完成这项工作(糟糕的Rhino!),很难判断它是否在内部创建线程,因此,您唯一的解决方案是从该组中的线程中创建、加载和执行Rhino引擎及其脚本,当

Rhino引擎是否有一个api可以停止 脚本FIE在中间。例如,我有一个脚本文件,其中 有一个infinte循环。我怎么才能停止在中间执行呢? 当然,我可以停止启动Rhino引擎的jvm
超越剧本。但是我不想因为这个原因而终止整个jvm会话,因为我已经通过编程启动了脚本,Rhino引擎也在与我的应用程序相同的jvm中运行。

Rhino引擎需要任何机制来完成这项工作(糟糕的Rhino!),很难判断它是否在内部创建线程,因此,您唯一的解决方案是从该组中的线程中创建、加载和执行Rhino引擎及其脚本,当您想要杀死它时,使用。是的,它已经被弃用了,但是考虑到Rhino库没有合作,实在没有其他方法可以做到这一点。

可以使用以下方法停止运行JavaScript的执行

1) 创建虚拟调试器并将其附加到最初创建的上下文

mContext=Context.enter()
ObservingDebugger ObservingDebugger=新的ObservingDebugger()
setDebugger(observingDebugger,新整数(0))
mContext.setGeneratingDebug(true)
mContext.setOptimizationLevel(-1)

ObservingDebugger代码如下所示

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.debug.DebugFrame;
import org.mozilla.javascript.debug.DebuggableScript;
import org.mozilla.javascript.debug.Debugger;

public class ObservingDebugger implements Debugger 
{
boolean isDisconnected = false;

private DebugFrame debugFrame = null;

public boolean isDisconnected() {
    return isDisconnected;
}

public void setDisconnected(boolean isDisconnected) {
    this.isDisconnected = isDisconnected;
    if(debugFrame != null){
       ((ObservingDebugFrame)debugFrame).setDisconnected(isDisconnected);
    }
}

public ObservingDebugger() {

}

public DebugFrame getFrame(Context cx, DebuggableScript fnOrScript)
{
    if(debugFrame == null){
        debugFrame = new ObservingDebugFrame(isDisconnected);
    }
    return debugFrame;      
}

@Override
public void handleCompilationDone(Context arg0, DebuggableScript arg1, String arg2) {   } }
// internal ObservingDebugFrame class
class ObservingDebugFrame implements DebugFrame
   {
boolean isDisconnected = false;

public boolean isDisconnected() {
    return isDisconnected;
}

public void setDisconnected(boolean isDisconnected) {
    this.isDisconnected = isDisconnected;
}

ObservingDebugFrame(boolean isDisconnected)
{
    this.isDisconnected = isDisconnected;
}

public void onEnter(Context cx, Scriptable activation,
        Scriptable thisObj, Object[] args)
{ }

public void onLineChange(Context cx, int lineNumber) 
{
    if(isDisconnected){
        throw new RuntimeException("Script Execution terminaed");
    }
}

public void onExceptionThrown(Context cx, Throwable ex)
{ }

public void onExit(Context cx, boolean byThrow,
        Object resultOrException)
{ }

@Override
public void onDebuggerStatement(Context arg0) { } }
ObservingDebugger类将管理布尔变量“isDisconnected”,当用户单击停止按钮(希望停止执行)时,该变量将设置为true。变量设置为true后,Rhino执行将立即终止

observingDebugger.setDisconnected(true);

对于其他正在寻找解决方案的人,javadoc For ContextFactory详细介绍了如何停止运行超过10秒的脚本:


我使用ExecutorService在新线程中执行脚本,并超时future.get

    ExecutorService executor = Executors.newSingleThreadExecutor();

    Future<?> future = executor.submit(threadEvaluation);

    try {
        System.out.println("Started..");
        future.get(100, TimeUnit.MILLISECONDS);
        System.out.println("Finished!");
    } catch (TimeoutException e) {
        future.cancel(true);
        System.out.println("Terminated!");
    }
在创建任何上下文对象之前,您需要将应用程序配置为使用此ContextFactory作为默认值,只需调用

InterruptableContextFactory.init()
在Callable的call方法中,您可以捕获错误:

    try {
        cx.setOptimizationLevel(9);
        cx.setInstructionObserverThreshold(10000);
        ScriptableObject scope = cx.initStandardObjects();

        // your code here

    } catch (Error e) {
        System.out.println("execution was aborted: " + e.getMessage());
    } finally {
        Context.exit();
    }

@Donal:这可能不起作用,因为一旦我创建了新线程并开始加载和执行Rhino引擎,一旦上下文上的EvaluaterReader()方法被调用,线程执行完成,Rhino引擎内部管理执行。这就是为什么我建议将其放在自己的线程组中;Rhino创建的任何其他线程仍将位于该线程组(或子线程组)中,因此仍然可以将它们全部杀死。如果您在从java中读取javadoc时遇到问题,这里有一个HTML版本:我想知道这和调试器方法对性能的影响。有什么想法吗?我想调试器方法会对性能产生一些影响,因为上下文正在生成调试信息。ContextFactory解决方案只是在执行了一定数量的指令后触发。
    try {
        cx.setOptimizationLevel(9);
        cx.setInstructionObserverThreshold(10000);
        ScriptableObject scope = cx.initStandardObjects();

        // your code here

    } catch (Error e) {
        System.out.println("execution was aborted: " + e.getMessage());
    } finally {
        Context.exit();
    }