2014-01-27 11 views
1

자바 스크립팅 API를 사용하여 일부 사용자 정의 자바 스크립트의 실행을 제어하는 ​​데 어려움을 겪고 있습니다. 후드 아래에 내장 된 Rhino 엔진을 사용하고 있습니다.이 엔진은 InstructionObserverThreshold를 설정할 수 있으며 한계에 도달하면 실행을 중지합니다. 나는 잠시 동안 다음 예제 응용 프로그램을 가지고 노는 중이며, 왜 작동하지 않는지에 관해서 난처한 처지입니다. MaximumInterpreterStackDepth도 설정 한 것을 볼 수 있습니다. 이것은 완벽하게 작동하지만 지시 관찰자는 아무 것도하지 않는 것처럼 보입니다.javax.scripting 컨텍스트에서 InstructionObserverThreshold를 설정하십시오.

이 코드가 작동하지 않도록 무엇이 부족합니까에 대한 아이디어가 있습니까?

감사합니다.

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를 처리하는 권장 방법은 스크립팅 API에서 사용되는 기본 ContextFactory에서 제공되지 않습니다. 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 (factory) 메소드를 통해 자신의 컨텍스트 팩토리의 인스턴스를 삽입 할 수 있어야합니다.

그러나 내 테스트의 지시 관찰자는 최적화 수준이 < = 0 일 때만 작동합니다. 완벽하게 최적화 된 스크립트 - 모든 것이 바이트 코드로 컴파일되는 곳에서는 작동하지 않습니다. 나는 이것을 생산적인 시스템이 아닌 개발에만 사용하고 있습니다.

+0

나는 이것을 한 번에 시험해 보았다. 문제는 ContextFactory.initGlobal을 직접 호출 할 수 없다는 것입니다. ContextFactory.initGlobal을 호출하려고 시도하는 RhinoScriptEngine 클래스가 중단됩니다. 그것은 한 번만 호출 할 수 있으며 나중에 어떤 시도에서도 예외를 throw합니다. –

+0

좋아, RhinoScriptEngine을 사용하지 않아 이것이 저에게 효과적 일 수 있습니다. Context 객체를 직접 사용하여 "오래된"방법을 사용하고 있습니다 (https://developer.mozilla.org/en-US/docs/Rhino/Embedding_tutorial). –