Details
-
Bug
-
Status: Closed
-
Blocker
-
Resolution: Fixed
-
1.1-rc-2
-
None
-
None
Description
A deadlock can be created by two separate threads attempting to load classes from the same GroovyClassLoader. Reproducibility is non-deterministic as it seems to be a timing issue. The environment that produced the example stack trace below has the following features:
One thread is inside a call to groovyClassLoader.loadClass(scriptName, true, true);
One thread is inside a call to newInstance() on a Class returned by the previous call (on the same GroovyClassLoader)
Two different loaded scripts are involved in the two calls. Both scripts import other scripts (and therefore rely on the classloader to do recursive loading), though it's not clear whether that is an essential feature in causing the deadlock.
A straightforward solution might be to have the classCache calls (getClassCacheEntry, etc) synchronize on something else (like the cache itself) other than the loader, though it's not clear whether that would solve only this case or the general case.
Stacktraces:
Found one Java-level deadlock:
=============================
"resin-tcp-connection-*:8080-17":
waiting to lock monitor 0x080cff84 (object 0x4686f850, a groovy.lang.GroovyClassLoader),
which is held by "resin-tcp-connection-*:8080-1"
"resin-tcp-connection-*:8080-1":
waiting to lock monitor 0x080d0240 (object 0x4578aec0, a groovy.lang.GroovyClassLoader$InnerLoader),
which is held by "resin-tcp-connection-*:8080-17"
Java stack information for the threads listed above:
===================================================
"resin-tcp-connection-*:8080-17":
at groovy.lang.GroovyClassLoader.getClassCacheEntry(GroovyClassLoader.java:514)
- waiting to lock <0x4686f850> (a groovy.lang.GroovyClassLoader)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:620)
at groovy.lang.GroovyClassLoader$InnerLoader.loadClass(GroovyClassLoader.java:385)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:723)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) - locked <0x4578aec0> (a groovy.lang.GroovyClassLoader$InnerLoader)
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
at java.lang.Class.getConstructor0(Class.java:2699)
at java.lang.Class.newInstance0(Class.java:326)
at java.lang.Class.newInstance(Class.java:308)
...
"resin-tcp-connection-*:8080-1":
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.privateGetPublicFields(Class.java:2324)
at java.lang.Class.getFields(Class.java:1359)
at org.codehaus.groovy.classgen.Verifier.getTimestamp(Verifier.java:606)
at org.codehaus.groovy.control.ResolveVisitor.getTimeStamp(ResolveVisitor.java:185)
at org.codehaus.groovy.control.ResolveVisitor.isSourceNewer(ResolveVisitor.java:205)
at org.codehaus.groovy.control.ResolveVisitor.resolveToScript(ResolveVisitor.java:234)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:162)
at org.codehaus.groovy.control.ResolveVisitor.resolveFromModule(ResolveVisitor.java:388)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:162)
at org.codehaus.groovy.control.ResolveVisitor.resolve(ResolveVisitor.java:130)
at org.codehaus.groovy.control.ResolveVisitor.transformVariableExpression(ResolveVisitor.java:565)
at org.codehaus.groovy.control.ResolveVisitor.transform(ResolveVisitor.java:440)
at org.codehaus.groovy.control.ResolveVisitor.transformPropertyExpression(ResolveVisitor.java:532)
at org.codehaus.groovy.control.ResolveVisitor.transform(ResolveVisitor.java:442)
at org.codehaus.groovy.ast.expr.Expression.transformExpressions(Expression.java:49)
at org.codehaus.groovy.ast.expr.ArgumentListExpression.transformExpression(ArgumentListExpression.java:67)
at org.codehaus.groovy.control.ResolveVisitor.transform(ResolveVisitor.java:457)
at org.codehaus.groovy.control.ResolveVisitor.transformMethodCallExpression(ResolveVisitor.java:635)
at org.codehaus.groovy.control.ResolveVisitor.transform(ResolveVisitor.java:448)
at org.codehaus.groovy.control.ResolveVisitor.transformBinaryExpression(ResolveVisitor.java:603)
at org.codehaus.groovy.control.ResolveVisitor.transform(ResolveVisitor.java:446)
at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitExpressionStatement(ClassCodeExpressionTransformer.java:148)
at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:40)
at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:53)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:129)
at org.codehaus.groovy.control.ResolveVisitor.visitBlockStatement(ResolveVisitor.java:755)
at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:52)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:73)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:80)
at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitConstructorOrMethod(ClassCodeExpressionTransformer.java:53)
at org.codehaus.groovy.control.ResolveVisitor.visitConstructorOrMethod(ResolveVisitor.java:96)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:88)
at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:851)
at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:48)
at org.codehaus.groovy.control.ResolveVisitor.visitClass(ResolveVisitor.java:734)
at org.codehaus.groovy.control.ResolveVisitor.startResolving(ResolveVisitor.java:71)
at org.codehaus.groovy.control.CompilationUnit$5.call(CompilationUnit.java:527)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:772)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:438)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:289)
- locked <0x4686f850> (a groovy.lang.GroovyClassLoader)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:260)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:255)
at groovy.lang.GroovyClassLoader.recompile(GroovyClassLoader.java:708)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:668) - locked <0x4686f850> (a groovy.lang.GroovyClassLoader)
at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:497)
...