Как я могу выполнять groovy-скрипты в изолированном загрузчике классов?

Я пытаюсь запустить groovy-скрипты в изолированном загрузчике классов, чтобы они не выполнялись в контексте зависимостей вызывающего класса.

    Path log4j = Paths.get("..../lib/log4j-1.2.17.jar");
    Path groovy = Paths.get("..../lib/groovy-all-2.1.3.jar");
    RootLoader rootLoader = new RootLoader(new URL[] { log4j.toUri().toURL(), groovy.toUri().toURL() }, null);
    GroovyScriptEngine engine = new GroovyScriptEngine(".../src/main/resources", rootLoader);
    engine.run("Standalone.groovy", "");
Standalone.groovy:
import org.apache.log4j.BasicConfigurator
import org.apache.log4j.Logger

Logger logger = Logger.getLogger(getClass())
BasicConfigurator.configure()
logger.info("hello world")
pom.xml excerpt:
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.1.3</version>
    </dependency>

Любая вариация вышеизложенного, которую я пробовал, всегда приводит к

Exception in thread "main" groovy.lang.GroovyRuntimeException: Failed to create Script instance for class: class Standalone. Reason: java.lang.ClassCastException: Standalone cannot be cast to groovy.lang.GroovyObject
    at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:443)
    at groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:564)
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551)
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:537)

Я отследил это до groovy.util.GroovyScriptEngine#loadScriptByName, где скрипт анализируется в Class<T>, где T — имя самого скрипта.

Моя теория заключается в том, что это вызвано бинарной несовместимостью между средой выполнения groovy, работающей в вызывающем классе, и средой выполнения groovy, работающей в автономном загрузчике классов, из-за того, как groovy создает синтетические классы из сценариев посредством отражения.

Любые идеи о том, как это можно сделать?


person jordanpg    schedule 30.05.2017    source источник
comment
Я бы попытался также создать экземпляр GroovyScriptEngine из этого загрузчика классов. Похоже, сгенерированные классы не изолированы на 100%   -  person Tamas Hegedus    schedule 30.05.2017


Ответы (1)


попробуйте создать GroovyScriptEngine не напрямую, а через rootLoader.loadClass() и вызвать engine.run через рефлексию.

person daggett    schedule 30.05.2017