मैंने इसे समझ लिया। समस्या मैं में चल रहा था कि invokeFunction
एक NoSuchMethodException
फेंक क्योंकि कार्यों कस्टम स्क्रिप्ट द्वारा उजागर इंजन के डिफ़ॉल्ट दायरे से बाइंडिंग में मौजूद नहीं था होगा:
ScriptContext context = new SimpleScriptContext();
context.setBindings(nashorn.createBindings(), ScriptContext.ENGINE_SCOPE);
engine.eval(customScriptSource, context);
((Invocable) engine).invokeFunction(name, args); //<- NoSuchMethodException thrown
मैं बाहर खींच रहा था करना था तो क्या हुआ नाम से संदर्भ से समारोह और इतने की तरह स्पष्ट रूप से इसे कहते हैं:
JSObject function = (JSObject) context.getAttribute(name, ScriptContext.ENGINE_SCOPE);
function.call(null, args); //call to JSObject#isFunction omitted brevity
इस समारोह है कि अपने नए बनाए गए संदर्भ में मौजूद कॉल करेंगे। तुम भी वस्तुओं पर तरीकों इस तरह से आह्वान कर सकते हैं:
JSObject object = (JSObject) context.getAttribute(name, ScriptContext.ENGINE_SCOPE);
JSObject method = (JSObject) object.getMember(name);
method.call(object, args);
call
एक अनियंत्रित अपवाद फेंकता है (या तो Throwable
एक RuntimeException
या NashornException
कि जावास्क्रिप्ट stackframe जानकारी के साथ शुरू कर दिया गया में लिपटे) ताकि आप स्पष्ट रूप से संभाल करने के लिए है कि हो सकता है अगर आप उपयोगी प्रतिक्रिया प्रदान करना चाहते हैं।
इस तरह धागे एक-दूसरे पर कदम नहीं उठा सकते हैं क्योंकि प्रति थ्रेड एक अलग संदर्भ है। मैं धागे के बीच कस्टम रनटाइम-कोड साझा करने में सक्षम था और यह सुनिश्चित करता हूं कि कस्टम-रनटाइम द्वारा प्रकट म्यूटेबल-ऑब्जेक्ट्स में राज्य परिवर्तन संदर्भ द्वारा अलग किए गए थे।
ऐसा करने के लिए, मैं एक CompiledScript
उदाहरण है कि मेरे कस्टम क्रम-पुस्तकालय का एक संकलित प्रतिनिधित्व होता है बनाने के लिए:
public class Runtime {
private ScriptEngine engine;
private CompiledScript compiledRuntime;
public Runtime() {
engine = new NashornScriptEngineFactory().getScriptEngine("-strict");
String source = new Scanner(
this.getClass().getClassLoader().getResourceAsStream("runtime/runtime.js")
).useDelimiter("\\Z").next();
try {
compiledRuntime = ((Compilable) engine).compile(source);
} catch(ScriptException e) {
...
}
}
...
}
फिर जब मैं एक स्क्रिप्ट मैं संकलित स्रोत का मूल्यांकन पर अमल करने की जरूरत है, और उसके बाद का मूल्यांकन इस संदर्भ के खिलाफ स्क्रिप्ट के रूप में अच्छी तरह से:
ScriptContext context = new SimpleScriptContext();
context.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
//Exception handling omitted for brevity
//Evaluate the compiled runtime in our new context
compiledRuntime.eval(context);
//Evaluate the source in the same context
engine.eval(source, context);
//Call a function
JSObject jsObject = (JSObject) context.getAttribute(function, ScriptContext.ENGINE_SCOPE);
jsObject.call(null, args);
मैं इस एक से अधिक थ्रेड के साथ बाहर का परीक्षण किया और मुझे यकीन है कि राज्य में परिवर्तन संदर्भों है कि व्यक्ति धागे के हैं तक ही सीमित थे बनाने के लिए कर रहा था। ऐसा इसलिए है क्योंकि संकलित प्रतिनिधित्व को एक विशिष्ट संदर्भ में निष्पादित किया जाता है, जिसका अर्थ है कि इसके द्वारा प्रकट किए गए किसी भी चीज के उदाहरण उस संदर्भ में शामिल हैं।
यहां एक छोटा सा नुकसान यह है कि आप उन वस्तुओं के लिए ऑब्जेक्ट परिभाषाओं की अनावश्यक रूप से पुनर्मूल्यांकन कर सकते हैं जिनके पास थ्रेड-विशिष्ट स्थिति की आवश्यकता नहीं है। इस के आसपास पाने के लिए, सीधे इंजन पर इनका मूल्यांकन है, जो करने के लिए उन वस्तुओं के लिए बाइंडिंग जोड़ देगा इंजन के ENGINE_SCOPE
:
:
public Runtime() {
...
String shared = new Scanner(
this.getClass().getClassLoader().getResourceAsStream("runtime/shared.js")
).useDelimiter("\\Z").next();
try {
...
nashorn.eval(shared);
...
} catch(ScriptException e) {
...
}
}
बाद में
उसके बाद, आप इंजन के ENGINE_SCOPE
से धागे की विशिष्ट संदर्भ पॉप्युलेट कर सकते हैं
context.getBindings(ScriptContext.ENGINE_SCOPE).putAll(engine.getBindings(ScriptContext.ENGINE_SCOPE));
एक चीज आपको करने की आवश्यकता होगी यह सुनिश्चित कर लें कि ऐसी कोई भी वस्तु जिसे आप बेनकाब करते हैं, जमे हुए हैं। अन्यथा उन्हें फिर से परिभाषित करना या गुण जोड़ना संभव है।
मैंने पढ़ा है कि प्री-कंपाइलिंग वास्तव में नैशर्न में नो-ऑप है इसलिए इससे मदद नहीं मिलती है। हालांकि स्रोत नहीं मिल रहा है। मै गलत हो सकता हूँ। –