[
https://issues.apache.org/jira/browse/GROOVY-9541?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King closed GROOVY-9541.
-----------------------------
> Compiling statically using GroovyClassLoader does not always respect the
> configured parent ClassLoader
> ------------------------------------------------------------------------------------------------------
>
> Key: GROOVY-9541
> URL: https://issues.apache.org/jira/browse/GROOVY-9541
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 3.0.3
> Reporter: Lyuben Atanasov
> Assignee: Eric Milles
> Priority: Major
> Fix For: 3.0.14, 4.0.7
>
>
> When using GroovyClassLoader to parse a groovy script annotated with
> @CompileStatic, the static type checker does not seem to use the configured
> parent class loader. Instead it uses the thread context ClassLoader. This
> sometimes causes compilation failures (especially when Closures are present)
> in environments like OSGi, where the thread context ClassLoader is definitely
> not the desired ClassLoader.
> For example this code:
> {code:java}
> try (GroovyClassLoader classLoader = new GroovyClassLoader(bundleClassLoader,
> compilerConfiguration))
> {
> Class<?> scriptClass = classLoader.parseClass(scriptContent, scriptName);
> }
> {code}
> can fail like this:
> {noformat}
> java.lang.RuntimeException: java.lang.NoClassDefFoundError:
> groovy/lang/GroovyObject
> at
> org.codehaus.groovy.control.CompilationUnit$IPrimaryClassNodeOperation.doPhaseOperation(CompilationUnit.java:955)
> at
> org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:650)
> at
> org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:627)
> at
> groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:389)
> at
> groovy.lang.GroovyClassLoader.lambda$parseClass$3(GroovyClassLoader.java:332)
> at
> org.codehaus.groovy.runtime.memoize.StampedCommonCache.compute(StampedCommonCache.java:163)
> at
> org.codehaus.groovy.runtime.memoize.StampedCommonCache.getAndPut(StampedCommonCache.java:154)
> at
> groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:330)
> at
> groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:314)
> at
> groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:257)
> ....
> Caused by: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
> at java.lang.ClassLoader.defineClass1(Native Method)
> at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
> at java.lang.ClassLoader.defineClass(ClassLoader.java:636)
> at
> groovy.lang.GroovyClassLoader.defineClass(GroovyClassLoader.java:733)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evaluateExpression(StaticTypeCheckingSupport.java:2176)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.checkClosureWithDelegatesTo(StaticTypeCheckingVisitor.java:3101)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitMethodCallArguments(StaticTypeCheckingVisitor.java:2645)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitMethodCallExpression(StaticTypeCheckingVisitor.java:3482)
> at
> org.codehaus.groovy.transform.sc.StaticCompilationVisitor.visitMethodCallExpression(StaticCompilationVisitor.java:409)
> at
> org.codehaus.groovy.ast.expr.MethodCallExpression.visit(MethodCallExpression.java:76)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitBinaryExpression(StaticTypeCheckingVisitor.java:770)
> at
> org.codehaus.groovy.ast.CodeVisitorSupport.visitDeclarationExpression(CodeVisitorSupport.java:335)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitDeclarationExpression(ClassCodeVisitorSupport.java:150)
> at
> org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
> at
> org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:117)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:200)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitExpressionStatement(StaticTypeCheckingVisitor.java:2120)
> at
> org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:40)
> at
> org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:86)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:164)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitBlockStatement(StaticTypeCheckingVisitor.java:3825)
> at
> org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:69)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:138)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:111)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitConstructorOrMethod(StaticTypeCheckingVisitor.java:2109)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:106)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.startMethodInference(StaticTypeCheckingVisitor.java:2477)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitMethod(StaticTypeCheckingVisitor.java:2435)
> at
> org.codehaus.groovy.transform.sc.StaticCompilationVisitor.visitMethod(StaticCompilationVisitor.java:235)
> at org.codehaus.groovy.ast.ClassNode.visitMethods(ClassNode.java:1100)
> at
> org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1093)
> at
> org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:52)
> at
> org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.visitClass(StaticTypeCheckingVisitor.java:405)
> at
> org.codehaus.groovy.transform.sc.StaticCompilationVisitor.visitClass(StaticCompilationVisitor.java:193)
> at
> org.codehaus.groovy.transform.sc.StaticCompileTransformation.visit(StaticCompileTransformation.java:65)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at
> org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
> at
> org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:191)
> at
> org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
> at
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
> at
> org.codehaus.groovy.control.customizers.ASTTransformationCustomizer.call(ASTTransformationCustomizer.groovy:297)
> at
> org.codehaus.groovy.control.CompilationUnit$IPrimaryClassNodeOperation.doPhaseOperation(CompilationUnit.java:921)
> ... 30 more
> Caused by: java.lang.ClassNotFoundException: groovy.lang.GroovyObject
> at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
> at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
> at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:869)
> at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:979)
> at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:967)
> ... 75 more
> {noformat}
> This can happen if the compilation has been triggered by a thread started by
> another OSGi bundle that does not import groovy packages, even though the
> GroovyClassLoader has been explicitly created with the correct parent
> ClassLoader that can indeed access those packages.
> So far I have tracked the issue to
> {{org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport#evaluateExpression(final
> Expression, final CompilerConfiguration)}}
> where it creates a CompilationUnit without giving it a ClassLoader, which
> results in the CompilationUnit creating a default GroovyClassLoader with
> parent set to the thread context ClassLoader. I think thatÂ
> StaticTypeCheckingSupport should be able to pass the parent ClassLoader that
> the original GroovyClassLoader was configured with in order to avoid
> unexpected results.
> I don't know whether there are more places during static type checking where
> the issue could occur.
> The current workaround for this issue is to temporarily change the thread's
> context ClassLoader to the one that is given to the GroovyClassLoader before
> compiling a script, and then restoring the original context ClassLoader. This
> is, however, probably not possible in all environments.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)