2016-08-19 68 views
1

我正嘗試使用Nashorn創建Java程序的控制檯界面。所以我想要對某些默認導入進行評估。問題在於何時訪問未定義的值。理想情況下,engine.eval應該拋出一個ReferenceError,或返回null,但我後來得到不一致的值:訪問未定義的值後,Nashorn中的輸出不一致

import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x }")); 
    } 
} 

結果在ideone和Windows的Oracle JDK 1.8.0_101是:

null 
1 
null 

的最後的輸出是null,但添加x == null給出了錯誤。

我得到這個輸出,如果我添加任何空格的第一個字符串:

null 
1 
1 

看來,最後一個值是null如果第一個和最後engine.eval參數都完全一樣,包括空格。

x值可以回去null1所以它看起來像在發動機某種緩存之間:

import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x + x }")); 
     System.out.println(engine.eval("with(JavaImporter(java.util)) { x }")); 
    } 
} 

給出:

null 
1 
null 
1 
2.0 
null 

有什麼方法得到這個始終給出null, 1, 1的結果?

+0

'x'的值是* undefined *,not * null *。它只是通過'engine.eval'轉換爲* null *,以便將其返回給java。你有沒有嘗試'x === undefined'(注意'==='而不是'==','=='只是......壞,在javascript中它有非常不一致的行爲)? –

+0

我用'=='來包含它是'undefined'或'null'的可能性,但是我用什麼代碼都沒有關係,任何改變都會被重新處理爲'1'。用'x + x'代替'x'得到2,甚至在'x'周圍增加一個空格給出1.這就好像字符串的結果被引擎緩存並忽略了對該值的任何改變。 – fgb

+0

我認爲這可能是在退回到非嚴格模式時在nashorn中的錯誤(儘管我沒有找到任何參考)。值得注意的是'with(...){...}'語法已被棄用,並且不被'use strict'支持;'。完全刪除'with'語句使nashorn抱怨該變量未被聲明。 – RudolphEst

回答

0

存在發動機內的二級緩存,其可以通過與創建它被禁用:

NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); 
ScriptEngine engine = factory.getScriptEngine(new String[] { "--class-cache-size = 0" }); 

通過強制重新編譯每一個表情,似乎解決了問題。它看起來像是根據哪些變量在範圍內編譯不同。

0

強制引擎確認變量的聲明。

只需在第一個腳本中使用var x即可。

System.out.println(engine.eval("with(JavaImporter(java.util)) { var x }")); System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }")); System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));