groovy

Upgrading to Groovy 1.1 final snapshot causes LinkageError in Grails

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Blocker Blocker
  • Resolution: Won't Fix
  • Affects Version/s: 1.1-rc-2
  • Fix Version/s: 1.1-rc-3
  • Component/s: None
  • Labels:
    None
  • Number of attachments :
    0

Description

I have a clean Grails project with the following changeset where the Groovy jar is the latest build of 1.1 final:

the project i have has the following svn changeset
A lib/groovy-all-1.1-final-SNAPSHOT.jar
D lib/groovy-all-1.1-rc-1.jar
M bin/startGrails

When I run any Gant script in Grails (such as grails list-plugins) that depends on a W3C DOM class i get the error

java.lang.LinkageError: Class org/w3c/dom/UserDataHandler violates loader constraints
   at java.lang.ClassLoader.defineClass1(Native Method)
   at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
   at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
   at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
   at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
   at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
   at org.codehaus.groovy.tools.RootLoader.oldFindClass(RootLoader.java:142)
   at org.codehaus.groovy.tools.RootLoader.loadClass(RootLoader.java:114)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
   at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
   at java.lang.Class.getDeclaredMethods0(Native Method)
   at java.lang.Class.privateGetDeclaredMethods(Class.java:2395)
   at java.lang.Class.getDeclaredMethods(Class.java:1763)
   at org.codehaus.groovy.reflection.CachedClass.getMethods(CachedClass.java:131)
   at groovy.lang.MetaClassImpl.populateMethods(MetaClassImpl.java:238)
   at groovy.lang.MetaClassImpl.fillMethodIndex(MetaClassImpl.java:217)
   at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:2380)
   at groovy.lang.ExpandoMetaClass.initialize(ExpandoMetaClass.java:355)
   at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:164)
   at org.codehaus.groovy.runtime.Invoker.getProperty(Invoker.java:172)
   at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:157)
   at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:500)
   at ListPlugins_groovy.run(ListPlugins_groovy:61)

It appears to originate from a MetaClass look-up. This was not a problem before upgrading Groovy.

Activity

Hide
blackdrag blackdrag added a comment -

according to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4972409 they made this message better and I suggest you try it again with a java6, so we can know what the real problem is.

Show
blackdrag blackdrag added a comment - according to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4972409 they made this message better and I suggest you try it again with a java6, so we can know what the real problem is.
Hide
Graeme Rocher added a comment - - edited

Exception in 1.6 is:

Error executing script ListPlugins: loader constraint violation: loader (instanc
e of org/codehaus/groovy/tools/RootLoader) previously initiated loading for a di
fferent type with name "org/w3c/dom/UserDataHandler"
java.lang.LinkageError: loader constraint violation: loader (instance of org/cod
ehaus/groovy/tools/RootLoader) previously initiated loading for a different type
 with name "org/w3c/dom/UserDataHandler"
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:12
4)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at org.codehaus.groovy.tools.RootLoader.oldFindClass(RootLoader.java:142
)
        at org.codehaus.groovy.tools.RootLoader.loadClass(RootLoader.java:114)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
        at java.lang.Class.getDeclaredMethods(Class.java:1791)
        at org.codehaus.groovy.reflection.CachedClass.getMethods(CachedClass.jav
a:131)
        at groovy.lang.MetaClassImpl.populateMethods(MetaClassImpl.java:238)
        at groovy.lang.MetaClassImpl.fillMethodIndex(MetaClassImpl.java:217)
        at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:2380)
        at groovy.lang.ExpandoMetaClass.initialize(ExpandoMetaClass.java:355)
        at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaCl
ass(MetaClassRegistryImpl.java:164)
        at org.codehaus.groovy.runtime.Invoker.invokePojoMethod(Invoker.java:86)

        at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:75)
        at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.
java:66)
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(Scrip
tBytecodeAdapter.java:170)
        at ListPlugins_groovy.run(ListPlugins_groovy:55)

Still not a great deal of help

Show
Graeme Rocher added a comment - - edited Exception in 1.6 is:
Error executing script ListPlugins: loader constraint violation: loader (instanc
e of org/codehaus/groovy/tools/RootLoader) previously initiated loading for a di
fferent type with name "org/w3c/dom/UserDataHandler"
java.lang.LinkageError: loader constraint violation: loader (instance of org/cod
ehaus/groovy/tools/RootLoader) previously initiated loading for a different type
 with name "org/w3c/dom/UserDataHandler"
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:12
4)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at org.codehaus.groovy.tools.RootLoader.oldFindClass(RootLoader.java:142
)
        at org.codehaus.groovy.tools.RootLoader.loadClass(RootLoader.java:114)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
        at java.lang.Class.getDeclaredMethods(Class.java:1791)
        at org.codehaus.groovy.reflection.CachedClass.getMethods(CachedClass.jav
a:131)
        at groovy.lang.MetaClassImpl.populateMethods(MetaClassImpl.java:238)
        at groovy.lang.MetaClassImpl.fillMethodIndex(MetaClassImpl.java:217)
        at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:2380)
        at groovy.lang.ExpandoMetaClass.initialize(ExpandoMetaClass.java:355)
        at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaCl
ass(MetaClassRegistryImpl.java:164)
        at org.codehaus.groovy.runtime.Invoker.invokePojoMethod(Invoker.java:86)

        at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:75)
        at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.
java:66)
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(Scrip
tBytecodeAdapter.java:170)
        at ListPlugins_groovy.run(ListPlugins_groovy:55)
Still not a great deal of help
Hide
Graeme Rocher added a comment -

The problem was introduced in this changeset:

http://svn.groovy.codehaus.org/changelog/groovy/?cs=8612

Seems related to JDK proxy change

Show
Graeme Rocher added a comment - The problem was introduced in this changeset: http://svn.groovy.codehaus.org/changelog/groovy/?cs=8612 Seems related to JDK proxy change
Hide
Alex Tkachman added a comment -

jaxen.jar contains this class, which is also part of JDK. If remove it, everything works fine.

Show
Alex Tkachman added a comment - jaxen.jar contains this class, which is also part of JDK. If remove it, everything works fine.
Hide
Graeme Rocher added a comment -

Yes but if you remove Grails will no longer work on jdk 1.4 VMs as this class doesn't exist there. How do you suggest we override such a dependency?

Show
Graeme Rocher added a comment - Yes but if you remove Grails will no longer work on jdk 1.4 VMs as this class doesn't exist there. How do you suggest we override such a dependency?
Hide
Guillaume Laforge added a comment -

Does it mean we can't have anymore the same class in two different jars?
This is the kind of situation that happens all the time in app servers where the web app overrides the XML jars that are also availble in the app server.

Show
Guillaume Laforge added a comment - Does it mean we can't have anymore the same class in two different jars? This is the kind of situation that happens all the time in app servers where the web app overrides the XML jars that are also availble in the app server.
Hide
blackdrag blackdrag added a comment -

after extensive analysis I come to the concllusion that.. it really is jaxen which is the evil one here. RootLoader does not follow completely the constrains that a classloader should follow and because of that not all things are working that would work when using only normal classloaders. As far as I can tell jaxen includes the UserDataHandler for compatibility with 1.4, in java5 jaxen duplicates this class. As long as the same loader which is loading the xml stuff is also loading the jaxen.jar, there is no problem. But in our case RootLoader loads the jaxen jar and the system loader loads the xml stuff. Because of the special construction of the RootLoader we get the problem above... As a result the jaxen classes will use the jaxen UserDataHandler and the XML classes in rt.jar will use the UserDataHandler class from rt.jar. And that is not working.

I see several possible workarounds, but they all don't sound very good...

one would be to enforce the loading of UserDataHandler through the system loader. For this RootLoader would have to not to include the jaxen.jar yet, and gets it added later. That's something a gant script could do.

Another way would be to remove the UserDataHandler class from the jaxen.jar. You could still have it loaded for java1.4 when you say you set a property "java.v4.compatibility.path" for example and a line like this to the conf file:

load ${java.v4.compatibility.path}/*.jar

of course that means, that this should be in a directory that is normally not loaded. This directory would then for example contain a jar with the UserDataHandler class, while the normal jaxen.jar (without that class) would be in the standard lib directory.

And the last way would be to not to add jaxen.jar to the paths RootLoader handles, but to add jaxen.jar to the classpath the system classloader gets. Of course any xml stuff would have to be in this classpath as well.

And the last workaround would be to define a custom system classloader, by setting java.system.class.loader. That ClassLoader would have to extend RootLoader and would need to configure itself. Such a loader could prefer the classes in the conf file.. but for this the startup process of Groovy would need adaption. So it is no solution you can do quickly

Show
blackdrag blackdrag added a comment - after extensive analysis I come to the concllusion that.. it really is jaxen which is the evil one here. RootLoader does not follow completely the constrains that a classloader should follow and because of that not all things are working that would work when using only normal classloaders. As far as I can tell jaxen includes the UserDataHandler for compatibility with 1.4, in java5 jaxen duplicates this class. As long as the same loader which is loading the xml stuff is also loading the jaxen.jar, there is no problem. But in our case RootLoader loads the jaxen jar and the system loader loads the xml stuff. Because of the special construction of the RootLoader we get the problem above... As a result the jaxen classes will use the jaxen UserDataHandler and the XML classes in rt.jar will use the UserDataHandler class from rt.jar. And that is not working. I see several possible workarounds, but they all don't sound very good... one would be to enforce the loading of UserDataHandler through the system loader. For this RootLoader would have to not to include the jaxen.jar yet, and gets it added later. That's something a gant script could do. Another way would be to remove the UserDataHandler class from the jaxen.jar. You could still have it loaded for java1.4 when you say you set a property "java.v4.compatibility.path" for example and a line like this to the conf file:
load ${java.v4.compatibility.path}/*.jar
of course that means, that this should be in a directory that is normally not loaded. This directory would then for example contain a jar with the UserDataHandler class, while the normal jaxen.jar (without that class) would be in the standard lib directory. And the last way would be to not to add jaxen.jar to the paths RootLoader handles, but to add jaxen.jar to the classpath the system classloader gets. Of course any xml stuff would have to be in this classpath as well. And the last workaround would be to define a custom system classloader, by setting java.system.class.loader. That ClassLoader would have to extend RootLoader and would need to configure itself. Such a loader could prefer the classes in the conf file.. but for this the startup process of Groovy would need adaption. So it is no solution you can do quickly
Hide
Alex Tkachman added a comment -

Graeme, I think what Jochen says is that we can do nothing on Groovy side but should solve the issue on Grails side.

Show
Alex Tkachman added a comment - Graeme, I think what Jochen says is that we can do nothing on Groovy side but should solve the issue on Grails side.
Hide
Guillaume Laforge added a comment -

So, at this point, I think we can't do too much regarding this error.
I'm closing it as won't fix for now, crossing fingers for the problem not to be bigger than what we expect – as having two libraries in different classloaders is a pretty common scenario in app servers I'm afraid.
We'll reopen the issue if a fix is needed that no workaround would solve.

Show
Guillaume Laforge added a comment - So, at this point, I think we can't do too much regarding this error. I'm closing it as won't fix for now, crossing fingers for the problem not to be bigger than what we expect – as having two libraries in different classloaders is a pretty common scenario in app servers I'm afraid. We'll reopen the issue if a fix is needed that no workaround would solve.
Hide
Ganesh Krishnan added a comment -

Deleting the .ivy2/cache folder fixes the problem for me.

Show
Ganesh Krishnan added a comment - Deleting the .ivy2/cache folder fixes the problem for me.

People

Vote (0)
Watch (5)

Dates

  • Created:
    Updated:
    Resolved: