ScriptEngineManagerのコンストラクタにClassLoaderを与えても、スクリプトがそのClassLoaderの元で動作するわけではない。
[intlink id=”190″]でScriptEngineManagerを生成するときにClassLoaderを設定できるようなことを書きました。実験しているうちに、そんなに甘くないことがわかりました。
実験コード
クラスローダ(=tClassLoader)を作って、そこからクラス(=OTL)のインスタンスをnewしてみる。
その後で、スクリプトでも同じようにインスタンスをnewしてみる。
public class ScriptEngineClassLoaderTest {
public static void main(String[] aArguments) throws MalformedURLException, ClassNotFoundException, ScriptException {
URLClassLoader tClassLoader = new URLClassLoader(new URL[] { new URL("file:../testtest/bin/") });
System.out.println("load: " + tClassLoader.loadClass("OTL"));
System.out.println("--------- スクリプトエンジンで new してみる ---------");
ScriptEngineManager tScriptEngineManager = new ScriptEngineManager(tClassLoader);
tScriptEngineManager.getEngineByName("groovy").eval("new OTL();");
}
}
実行結果
load: class OTL --------- スクリプトエンジンで new してみる --------- Exception in thread "main" javax.script.ScriptException: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, Script1.groovy: 1: unable to resolve class OTL @ line 1, column 1. 1 error at com.sun.script.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:114) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247) at jp.kurusugawa.benchmark.scriptengine.ScriptEngineClassLoaderTest.main(ScriptEngineClassLoaderTest.java:16) Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, Script1.groovy: 1: unable to resolve class OTL @ line 1, column 1. 1 error at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:326) at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:847) at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:476) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:309) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:279) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:274) at com.sun.script.groovy.GroovyScriptEngine.getScriptClass(GroovyScriptEngine.java:275) at com.sun.script.groovy.GroovyScriptEngine.eval(GroovyScriptEngine.java:108) ... 2 more
クラス(=OTL)が見つからないそうです。
javascriptでも試す。
tScriptEngineManager.getEngineByName("javascript").eval("new OTL();");
load: class OTL --------- スクリプトエンジンで new してみる --------- Exception in thread "main" javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "OTL" is not defined. (#1) in at line number 1 at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:110) at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:124) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247) at jp.kurusugawa.benchmark.scriptengine.ScriptEngineClassLoaderTest.main(ScriptEngineClassLoaderTest.java:16)
やっぱり見つからない・・・orz
コンストラクタに指定するClassLoaderの役割は
と言うわけで、ScriptEngineManagerのコンストラクタにClassLoaderを与えても、スクリプト実行時のClassLoaderは差し替えれないようです。
では、ScriptEngineManagerのコンストラクタに与えるClassLoaderはどういう意味を持っているのかというと?
public class ScriptEngineClassLoaderTest {
public static void main(String[] args) throws MalformedURLException {
System.out.println("ClassLoaderを指定しないと・・・");
System.out.println("engine: " + new ScriptEngineManager().getEngineByName("groovy"));
System.out.println("ClassLoaderを指定すれば・・・");
System.out.println("engine: " + new ScriptEngineManager(new URLClassLoader(new URL[] { new URL("file:../groovy-engine/bin/") })).getEngineByName("groovy"));
}
}
ClassLoaderを指定しないと・・・ engine: null ClassLoaderを指定すれば・・・ engine: com.sun.script.groovy.GroovyScriptEngine@b6ece5
ScriptEngine自体のClassLoaderが指定できると言うことでした。
めちゃめちゃガッカリ。