Details
-
Type:
Bug
-
Status:
Open
-
Priority:
Critical
-
Resolution: Unresolved
-
Affects Version/s: 1.7.10
-
Fix Version/s: None
-
Component/s: Groovysh
-
Labels:None
Description
Sometimes we run into deadlocks in groovy shell. Looking at the threaddump below we see that threads pool-1-thread-1103 and pool-1-thread-1104 are deadlocked. I've looked in the issue list and similar issues looks be resolved but we're still experiencing it (for example GROOVY-4050).
The calls are made to different instance of GroovyShell.
"pool-1-thread-1104" - Thread t@219188
java.lang.Thread.State: BLOCKED on java.beans.PropertyDescriptor@3db8a1e8 owned by: pool-1-thread-1103
at java.beans.PropertyDescriptor.getReadMethod(Unknown Source)
at java.beans.Introspector.processPropertyDescriptors(Unknown Source)
at java.beans.Introspector.getTargetPropertyInfo(Unknown Source)
at java.beans.Introspector.getBeanInfo(Unknown Source)
at java.beans.Introspector.getBeanInfo(Unknown Source)
- locked java.lang.Object@5f70bea5
at groovy.lang.MetaClassImpl$15.run(MetaClassImpl.java:2940)
at java.security.AccessController.doPrivileged(Native Method)
at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:2938)
at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:2921) - locked groovy.lang.MetaClassImpl@4426073e
at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:166)
at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:182)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:210)
at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:751)
at groovy.lang.GroovyObjectSupport.<init>(GroovyObjectSupport.java:32)
at groovy.lang.Script.<init>(Script.java:40)
at groovy.lang.Script.<init>(Script.java:37)
at Script1.<init>(Script1.groovy)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:408)
at groovy.lang.GroovyShell.parse(GroovyShell.java:743)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:578)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:618)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:589)
-------
"pool-1-thread-1103" - Thread t@219187
java.lang.Thread.State: BLOCKED on java.lang.Object@5f70bea5 owned by: pool-1-thread-1104
at java.beans.Introspector.getPublicDeclaredMethods(Unknown Source)
at java.beans.Introspector.internalFindMethod(Unknown Source)
at java.beans.Introspector.findMethod(Unknown Source)
at java.beans.Introspector.findMethod(Unknown Source)
at java.beans.PropertyDescriptor.getReadMethod(Unknown Source)
- locked java.beans.PropertyDescriptor@3db8a1e8
at groovy.lang.MetaClassImpl.applyPropertyDescriptors(MetaClassImpl.java:2215)
at groovy.lang.MetaClassImpl.setupProperties(MetaClassImpl.java:1995)
at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:2950)
at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:2921) - locked groovy.lang.MetaClassImpl@71ea1b61
at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:166)
at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:182)
at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:210)
at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:751)
at groovy.lang.GroovyObjectSupport.<init>(GroovyObjectSupport.java:32)
at groovy.lang.Script.<init>(Script.java:40)
at groovy.lang.Script.<init>(Script.java:37)
at Script1.<init>(Script1.groovy)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:408)
at groovy.lang.GroovyShell.parse(GroovyShell.java:743)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:578)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:618)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:589)
As far as I can tell Object@5f70bea5 is the BEANINFO_CACHE used by the Introspector internally to sync the cache access. And PropertyDescriptor#getReadMethod is synchronized. Looks like this usage of Introspector and PropertyDescriptor can lead to a deadlock. The question is what we can do about this.
One way would be to replace the Introspector completely with... well I don't have anything at hand. The other way would be to pay a big performance penalty and sync in the Introspector, so only one MetaClassImpl can access it. But even then this deadlock could happen in combination with custom other code working with the Introspector. I would use the BEANINFO_CACHE, but it is internal.