検索 K
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@b6ece5ScriptEngine自体のClassLoaderが指定できると言うことでした。 めちゃめちゃガッカリ。
