Java 如何杀死犀牛剧本

Java 如何杀死犀牛剧本,java,rhino,Java,Rhino,我们正在使用Rhino在Java应用程序中执行Javascript。我们利用了一些Rhino特有的功能,因此无法升级到Nashorn。 我们面临的问题是,脚本是由用户创建的,当我们执行它们时,如果出现类似无限循环的错误,它将永远执行下去。我们想设定一个30秒左右的时间限制。 有没有办法在超时时终止脚本?您可以通过创建一个虚拟调试器来停止循环运行,并直接将其添加到javascript中,如下所示: mContext = Context.enter(); ObservingDebugger obse

我们正在使用Rhino在Java应用程序中执行Javascript。我们利用了一些Rhino特有的功能,因此无法升级到Nashorn。 我们面临的问题是,脚本是由用户创建的,当我们执行它们时,如果出现类似无限循环的错误,它将永远执行下去。我们想设定一个30秒左右的时间限制。
有没有办法在超时时终止脚本?

您可以通过创建一个虚拟调试器来停止循环运行,并直接将其添加到javascript中,如下所示:

mContext = Context.enter();
ObservingDebugger observingDebugger = new ObservingDebugger();
mContext.setDebugger(observingDebugger, new Integer(0));
mContext.setGeneratingDebug(true);
mContext.setOptimizationLevel(-1);
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) { } }
public class ScriptDynamicScopeFactory extends ContextFactory {
    @Override
    protected Context makeContext() {
        ScriptContext ctx = new ScriptContext();
        ctx.setInstructionObserverThreshold(10000);
        return ctx;
    }

    @Override
    protected void observeInstructionCount(Context ctx, int instructionCount) {
      long currentTime = System.currentTimeMillis();
      long executionTime = (currentTime - ((ScriptContext) ctx).startTime());
      // do something if execution time is greater then your timeout
    }
}
然后通过java程序创建一个如下所示的类:

mContext = Context.enter();
ObservingDebugger observingDebugger = new ObservingDebugger();
mContext.setDebugger(observingDebugger, new Integer(0));
mContext.setGeneratingDebug(true);
mContext.setOptimizationLevel(-1);
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) { } }
public class ScriptDynamicScopeFactory extends ContextFactory {
    @Override
    protected Context makeContext() {
        ScriptContext ctx = new ScriptContext();
        ctx.setInstructionObserverThreshold(10000);
        return ctx;
    }

    @Override
    protected void observeInstructionCount(Context ctx, int instructionCount) {
      long currentTime = System.currentTimeMillis();
      long executionTime = (currentTime - ((ScriptContext) ctx).startTime());
      // do something if execution time is greater then your timeout
    }
}
然后,要设置程序的计时器,请导入:

import java.util.Timer;
然后为ObservingDebugger设置计时器首选项:

timer.schedule(new TimerTask() {
  @Override
  public void run() {
   // code here
  }
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

您应该扩展
ContextFactory
类并重写方法
observeInstructionCount(Context ctx,int-instructionCount)
。Rhino将定期调用此方法,您可以通过以下方式检查它到目前为止运行了多长时间:

mContext = Context.enter();
ObservingDebugger observingDebugger = new ObservingDebugger();
mContext.setDebugger(observingDebugger, new Integer(0));
mContext.setGeneratingDebug(true);
mContext.setOptimizationLevel(-1);
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) { } }
public class ScriptDynamicScopeFactory extends ContextFactory {
    @Override
    protected Context makeContext() {
        ScriptContext ctx = new ScriptContext();
        ctx.setInstructionObserverThreshold(10000);
        return ctx;
    }

    @Override
    protected void observeInstructionCount(Context ctx, int instructionCount) {
      long currentTime = System.currentTimeMillis();
      long executionTime = (currentTime - ((ScriptContext) ctx).startTime());
      // do something if execution time is greater then your timeout
    }
}

请注意,您还需要重写
makeContext()
,以设置调用观察者的频率。请记住,这是执行的指令数,这意味着它不会每X毫秒被一致调用一次。如果一条指令需要花费很多时间(例如,调用Java应用程序),这可能不会很好地工作,但我认为它在几乎所有情况下都会做得很好。

您如何启动这些脚本?