Не найдено подходящего загрузчика классов для захвата

У меня есть это в начале класса:

@Grab(group = 'org.ccil.cowan.tagsoup', module = 'tagsoup', version = '1.2')
class MyClass{...

Я пытаюсь unit test этот класс, но всякий раз, когда я пытаюсь запустить тесты JUnit 4, я получаю эту ошибку:

Caused by: java.lang.RuntimeException: No suitable ClassLoader found for grab
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:52)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:198)
    at groovy.grape.GrapeIvy.chooseClassLoader(GrapeIvy.groovy:163)
    at groovy.grape.GrapeIvy$chooseClassLoader.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
    at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:227)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:225)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:51)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:153)
    at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:216)
    at groovy.grape.Grape.grab(Grape.java:131)
    at groovy.grape.Grape$grab.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:165)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:173)
    at ammoscanner.AmmoScanner.<clinit>(AmmoScanner.groovy)
    ... 30 more

Любые идеи? Я использую groovy 1.7.5

Ответы

Ответ 1

Использование @Grab делает код неустойчивым, по крайней мере, с 01/26/2011.

Ответ 2

Проблема

Рассматривая исходный код, это исключение генерируется всякий раз, когда указанное имя класса ClassLoader (или его суперклассы) не groovy.lang.GroovyClassLoader или org.codehaus.groovy.tools.RootLoader. то есть целевой класс-загрузчик должен быть экземпляром вышеупомянутых классов (бит-ограничение IMHO).

Решение

В настоящее время я не знаю, как настроить определенный загрузчик классов с помощью аннотаций @Grape/@Grab/@GrabConfig. Наиболее близким было бы использовать @GrabConfig(systemClassLoader=true) и обеспечить, чтобы Systemloader был экземпляром одного из вышеперечисленных классов ClassLoader.

Если кто-нибудь знает, сообщите мне (и я обновлю этот ответ).

Обходное решение

Следующий код программно загрузит ваш Grapes и загрузит их в поставляемый GroovyClassLoader (правда, не совсем то, что вы хотите).

def loadGrapes(){
    ClassLoader classLoader = new groovy.lang.GroovyClassLoader()
    Map[] grapez = [[group : 'org.ccil.cowan.tagsoup', module : 'tagsoup', version : '1.2']]
    Grape.grab(classLoader: classLoader, grapez)
    println "Class: " + classLoader.loadClass('org.ccil.cowan.tagsoup.jaxp.SAXParserImpl')
}

Ответ 3

Я предполагаю, что вы пробовали добавить

@GrabConfig(systemClassLoader=true)

так:

@Grapes([
    @Grab(group = 'org.ccil.cowan.tagsoup', module = 'tagsoup', version = '1.2'),
    @GrabConfig( systemClassLoader=true )
])
class MyClass{...

Ответ 4

Если вы не используете systemClassLoader = true, то кажется, что ваша среда IDE не кодирует код с помощью компилятора groovy, вы можете проверить это с помощью простого класса groovy, который выводит имя класса своего загрузчика классов. Я бы предположил, что он пытается скомпилировать классы groovy и запустить их с загрузчиком классов

См. также этот ответ на общую ошибку во время преобразования: для захвата не найдено подходящего ClassLoader. Кроме того, это сообщение в блоге объясняет больше о запуске предварительно скомпилированных классов groovy с загрузчиком классов.