我一直在努力解决使用java脚本API控制某些用户定义的javascript执行的问题。我在引擎盖下使用内置的Rhino引擎,它说你可以设置InstructionObserverThreshold,如果达到限制,它将负责停止执行。我已经玩了下面的示例应用程序一段时间了,我很难过为什么它不起作用。您将看到我已设置MaximumInterpreterStackDepth。这很有效,但指令观察者似乎没有做任何事情。
有关此代码缺少什么的任何想法,以使其工作?
谢谢!
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import com.sun.script.javascript.RhinoScriptEngine;
public class RhinoTester2 {
public static void main(String[] args) {
new RhinoScriptEngine(); // initialize the global context.
sun.org.mozilla.javascript.internal.ContextFactory cx = sun.org.mozilla.javascript.internal.ContextFactory.getGlobal();
cx.addListener( new sun.org.mozilla.javascript.internal.ContextFactory.Listener() {
public void contextCreated( sun.org.mozilla.javascript.internal.Context cxt ) {
cxt.setInstructionObserverThreshold(10000 ); // This should stop after 10 seconds or so.
cxt.setMaximumInterpreterStackDepth(1); // this should not be a factor for the moment
System.out.println("Context Factory threshold set. "+cxt.getInstructionObserverThreshold());
}
@Override
public void contextReleased(
sun.org.mozilla.javascript.internal.Context arg0) {
System.out.println("Context Released.");
}
});
// Now run the script to see if it will be stopped after a short time.
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("javascript");
try {
// engine.eval("while(true){println(\"hello\");};"); // This will fail immediately due to the interpreter stack depth.
engine.eval("while(true){};"); // this never fails. runs happily forever.
} catch (ScriptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
答案 0 :(得分:0)
您可以使用自己的ContextFactory覆盖版本来执行上下文操作。在方法makeContext()中,您可以从头开始创建上下文并设置您想要的指令计数以及其他设置。
我的实施示例:
public class MyContextFactory extends ContextFactory {
protected Context makeContext() {
Context cx = new MyContext(this);
cx.setOptimizationLevel(0);
cx.setLanguageVersion(Context.VERSION_1_8);
cx.setInstructionObserverThreshold(100000);
return cx;
}
}
正如您所看到的,我还创建了自己的Context子类,因为将工厂作为参数的Context构造函数受到保护:
public class RhinoContext extends Context {
public RhinoContext(ContextFactory factory) {
super(factory);
}
}
然后,您应该能够在调用任何脚本之前通过方法ContextFactory.initGlobal(factory)注入您自己的上下文工厂的实例。
但请注意,我的测试中的指令观察者仅在优化级别<= 0时才有效。在完全优化的脚本中 - 所有内容都编译为字节码 - 这不起作用。我自己只在开发中使用它,而不是在生产系统上使用它。