是否Rhino引擎有一个API,可以在中途停止脚本外商投资企业的执行。 例如,我在其中有一个infinte循环的脚本文件。 我怎么能中途停止执行?
当然,我可以停止赖以起家的犀牛引擎excecute脚本中的JVM。 但我并不想杀死整个JVM会因为这个原因,我已经开始编程脚本和犀牛引擎也在同一JVM中我的应用程序运行。
是否Rhino引擎有一个API,可以在中途停止脚本外商投资企业的执行。 例如,我在其中有一个infinte循环的脚本文件。 我怎么能中途停止执行?
当然,我可以停止赖以起家的犀牛引擎excecute脚本中的JVM。 但我并不想杀死整个JVM会因为这个原因,我已经开始编程脚本和犀牛引擎也在同一JVM中我的应用程序运行。
停止运行的JavaScript的执行可以通过以下方式进行。
1)创建一个虚拟调试器并将它附加到最初创建的上下文。
mContext = Context.enter();
ObservingDebugger observingDebugger =新ObservingDebugger();
mContext.setDebugger(observingDebugger,新的整数(0));
mContext.setGeneratingDebug(真);
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,如下犀牛执行将立即终止。
observingDebugger.setDisconnected(true);
为别人寻找一个解决方案,为ContextFactory的Javadoc详细介绍了如何阻止脚本运行时间超过10秒:
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/ContextFactory.java
我在一个新的线程使用的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:
public class InterruptableContextFactory extends ContextFactory {
public static boolean initialized = false;
public static void init() {
if (!initialized) {
ContextFactory.initGlobal(new InterruptableContextFactory());
initialized = true;
}
}
@Override
protected void observeInstructionCount(Context cx, int instructionCount) {
System.out.println(instructionCount + " javascript instructions!");
if (Thread.currentThread().isInterrupted()) {
throw new Error("script execution aborted");
}
}
@Override
protected Context makeContext() {
Context cx = super.makeContext();
//set a number of instructions here
cx.setInstructionObserverThreshold(10000);
return cx;
}
}
创建任何上下文对象之前,你需要配置你的应用程序使用此ContextFactory为默认值,只需调用
InterruptableContextFactory.init()
里面的可赎回的呼叫的方法,你可以捕捉到错误:
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();
}
Rhino引擎没有出现有这样做的(坏犀牛!)任何机制,很难判断它是否在内部创建线程,因此你所拥有的唯一解决方案是创建一个ThreadGroup
,加载和执行Rhino引擎和它的脚本该组中的一个线程里面,当你想杀死它,使用ThreadGroup.stop()
是的,这是过时的,但真的没有其他办法做到这一点因为有一个在犀牛库的部分没有合作。