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