2014-01-27 6 views
1

Я столкнулся с проблемой с использованием java-скриптового API для управления выполнением определенного javascript. Я использую встроенный движок Rhino под капотом, который говорит, что вы можете установить InstructionObserverThreshold, и он позаботится о прекращении выполнения, если достигнут предел. Я играю со следующим примерным приложением некоторое время, и я в тупике, почему он не будет работать. Вы увидите, что я установил MaximumInterpreterStackDepth. Это работает отлично, но наблюдатель инструкций ничего не делает.Настройка InstructionObserverThreshold в контексте javax.scripting

Любые идеи о том, чего не хватает с помощью этого кода, чтобы заставить его работать?

Спасибо!

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

К сожалению, похоже, что рекомендуемый способ обработки InstructionObservationCount не предоставляется в базе ContextFactory, используемой скриптом api. При взгляде на RhinoScriptEngine пользователь заблокирован от изменения ContextFactory, чтобы добавить реализацию (закрытый класс и анонимный статический блок, вызывающий initGlobal). Из того, что я могу сказать, у вас есть только два варианта: либо создайте свой собственный движок сценария, либо замените встроенную версию, либо управляйте ею в потоке и убейте поток, когда он превысит тайм-аут. Разочарование ..... –

ответ

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; 
    } 
} 

Как вы можете видеть, что я также создать свой собственный контекст подкласс, так как конструктор контекста, который принимает завод как защищенный параметр:

public class RhinoContext extends Context { 

    public RhinoContext(ContextFactory factory) { 
     super(factory); 
    } 

} 

Тогда вы должен иметь возможность вводить экземпляр собственной фабрики контекстов с помощью метода ContextFactory.initGlobal (фабрика) перед вызовом любых скриптов.

Обратите внимание, что наблюдатель команд в моих тестах работает только тогда, когда уровень оптимизации < = 0. В полностью оптимизированных сценариях - где все скомпилировано в байт-код - это не работает. Я использую это сам только в разработке, а не в продуктивных системах.

+0

Я пробовал это в какой-то момент. Проблема в том, что вы не можете сами вызвать ContextFactory.initGlobal. Он сломает класс RhinoScriptEngine, который пытается вызвать ContextFactory.initGlobal. Он может быть вызван только один раз и затем будет вызывать исключение в любой попытке. –

+0

Хорошо, я не использую RhinoScriptEngine, возможно, поэтому это работает для меня. Я все еще использую «старый» способ, используя объект Context, описанный здесь (здесь) (https://developer.mozilla.org/en-US/docs/Rhino/Embedding_tutorial). –

 Смежные вопросы

  • Нет связанных вопросов^_^