I figured it out: The GroovyShell belongs to the parent classloader and thus ginq cannot find it when the classloader lacks a parent. One solution is to use the parentless classloader to create the GroovyShell e.g:
var c = cl.loadClass("groovy.lang.GroovyShell"); var shell = c.getDeclaredConstructor().newInstance(); c.getMethod("evaluate", String.class).invoke(shell, script); Another way is to use a ProcessBuilder but that is much more involved for my current use case. Regards, Per From: Per Nyfelt <p...@alipsa.se> Organisation: Alipsa HB Reply to: "users@groovy.apache.org" <users@groovy.apache.org> Date: Monday, 28 April 2025 at 20:23 To: "users@groovy.apache.org" <users@groovy.apache.org> Subject: Running ginq from a "clean" classloader Hi, I am experimenting with running groovy scripts in a "clean" environment i.e. in a GroovyClassloader that does not have a parent. Background: One of my OSS projects is an analytics IDE where i want to enable users to run scripts that only has the dependencies of a gradle build script and hence i need to separate the IDE classloader from the one running the script. However, i have run into an issue with ginq expressions that baffles me. A complete but minimal example is here: https://github.com/perNyfelt/groovy-issues/tree/main/NoParentCL but the issue is basically: The groovy script is def numbers = [0, 1, 2] println "Numbers are $numbers" var result = GQ { from n in numbers where n > 0 select n } println "Ginq result is $result" After creating the GroovyClassloader i add the following files to the classpath: groovy-4.0.26.jar, groovy-ginq-4.0.26.jar, groovy-macro-4.0.26.jar When is do new GroovyShell(new GroovyClassloader()).evaluate(script) everything works fine but if i do new GroovyShell(new GroovyClassloader((Classloader)null).evaluate(script) I get Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: Script1.GQ() is applicable for argument types: (Script1$_run_closure1) values: [Script1$_run_closure1@5cb5bb88] Possible solutions: is(java.lang.Object), run(), run(), any(), grep(), any(groovy.lang.Closure) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:72) at org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.unwrap(IndyGuardsFiltersAndSignatures.java:163) at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321) at Script1.run(Script1.groovy:3) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328) at groovy.lang.MetaClassImpl.doInvokeMethod(MetaClassImpl.java:1333) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1088) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007) at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:633) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:624) at org.codehaus.groovy.runtime.InvokerHelper$1.run(InvokerHelper.java:461) at groovy.lang.GroovyShell.evaluate(GroovyShell.java:460) at groovy.lang.GroovyShell.evaluate(GroovyShell.java:495) at groovy.lang.GroovyShell.evaluate(GroovyShell.java:469) at RunScript.runScript(RunScript.java:37) at RunScript.main(RunScript.java:18) Does anyone know why that would be the case and/or a possible workaround? Regards, Per