dev@glassfish.java.net

Re: ClassCircularityError reported with the latest v3 trunk

From: Richard S. Hall <heavy_at_ungoverned.org>
Date: Mon, 20 Apr 2009 14:00:55 -0400

To be clear. This still doesn't look like a bug in Felix, it looks like
a bug in the JDK. We are just going to try to work around it in Felix to
avoid calling Class.getEnclosingClass().

-> richard

On 4/19/09 4:43 PM, Vivek Pandey wrote:
> Update on this: Richard's patched felix.jar seem to fix this issue. In
> another week or so there will be a point release of felix and
> integration of this release in glassfish should take care of this issue.
>
> Issue, https://glassfish.dev.java.net/issues/show_bug.cgi?id=7648 is
> updated accordingly.
>
> Thanks Richard for working on the fix and providing the patch!
>
> -vivek.
>
> Vivek Pandey wrote:
>>
>> Richard S. Hall wrote:
>>> This code in Felix should only ever be executed when there is a CNFE
>>> that is going to be thrown. Do you know if you should correctly be
>>> getting a CNFE?
>>>
>> Yes, a CNFE is expected as these classes are expected to be loaded by
>> the URLClassLoader. Here Felix's ModuleClassLoader is the parent of
>> this URLClassLoader.
>>
>>> To be clear, the explicit issue we are talking about is this change
>>> in Felix:
>>>
>>> http://issues.apache.org/jira/browse/FELIX-962
>>>
>>> We actually try to determine if a class is an inner class of a class
>>> loader when we are trying to guess whether or not we should delegate
>>> to the parent class loader. This is part of a hack which is a last
>>> ditch effort to avoid CNFE for bad JRE code that assumes it should
>>> be able to see everything on the class path from any class loader.
>>>
>>> The change from FELIX-962 is actually implemented in two different
>>> ways, one for JDK < 1.5 and one for JDK >= 1.5. In the >= 1.5
>>> version we use the method Class.getEnclosingClass(), which seems to
>>> cause the error for perhaps the reasons in the JDK bug you
>>> referenced. We implemented the two different approaches since we
>>> assumed performance would be better by just using
>>> getEnclosingClass() than trying to figure it out the enclosing class
>>> manually, which involves doing a class load.
>>>
>> Thanks this explians. Although the JDK bug might be the cause of
>> this, although trying to introspect the class while it is in
>> ClassLoader.loadClass() can get you in to this sort of issues. IOW,
>> it might be JVM spec level limitation vs a real bug in JDK.
>>> We could potentially try always using the < 1.5 approach, which does
>>> not use that method. If I created a felix.jar that did that, could
>>> you test it to see if it resolved the issue?
>>
>> Yes sure! Send it to me and will test it out.
>>
>> thanks,
>>
>> -vivek.
>>>
>>> -> richard
>>>
>>> On 4/18/09 11:39 PM, Vivek Pandey wrote:
>>>> I guess, I tried various things on my end to work around this
>>>> issue. Given that the bug is there since 2007 and not sure when JDK
>>>> will fix it. On our side we need a workaround. With this issue we
>>>> wont have jruby working on glassfish :-(
>>>>
>>>> -vivek.
>>>>
>>>> Richard S. Hall wrote:
>>>>> From reading the JDK bug description, this definitely sounds like
>>>>> it is related to that bug, since Felix is trying to determine the
>>>>> relationship among an inner and outer class.
>>>>>
>>>>> -> richard
>>>>>
>>>>> On 4/18/09 8:52 PM, Vivek Pandey wrote:
>>>>>> [Adding Richard Hall and dev alias]
>>>>>>
>>>>>> Ok, so the root cause is upgrade to Felix 1.6.0. Not sure if
>>>>>> FELIX-851[2] is causing this to happen. Basically Felix
>>>>>> ModuleClassLoader is the parent class loader of the
>>>>>> URLClassLoader using which all of jruby runtime classes are
>>>>>> loaded. There is some logic in felix where it tries to determine
>>>>>> the enclosing class of inner classes and thats where a
>>>>>> ClassCircularityError is reported.
>>>>>>
>>>>>> Although it is ignored from inside Felix but somehow this
>>>>>> behavior of determining if a class being loaded is requested by
>>>>>> the one from an OSGi bundle or not is causing certain instability
>>>>>> that latter on results in to more of ClassCirculatoryError. There
>>>>>> is JDK bugs [1] reported on jdk 5 and 6 as well.
>>>>>>
>>>>>> Here is the felix stack trace, where this error is reported:
>>>>>> http://pastie.org/451117
>>>>>>
>>>>>> This is the code in felix 1.6.0 branch where this error occurs:
>>>>>>
>>>>>> org.apache.felix.framework.searchpolicy.ModuleImpl:1287 (felix
>>>>>> 1.6.0 codebase)
>>>>>>
>>>>>> if (getEnclosingClassMethod != null)
>>>>>> {
>>>>>> try
>>>>>> {
>>>>>> Class enclosing = (Class)
>>>>>> getEnclosingClassMethod.invoke(clazz, null);
>>>>>> clazz = (enclosing != null) ? enclosing : clazz;
>>>>>> }
>>>>>> catch (Throwable t)
>>>>>> {
>>>>>> // Ignore everything and use original class.
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> Here is how I am loading classes:
>>>>>>
>>>>>> I have a jar file at: glassfish/modules/grizzly-jruby.jar.
>>>>>>
>>>>>> I use a URLClassLoader to load this jar file and also external
>>>>>> jars files (part of application/jruby jars). The classes are
>>>>>> loaded reflectively using this URLClassLoader. The parent of this
>>>>>> URLClassLoader is ModuleClassLoader from felix.
>>>>>>
>>>>>> The deployment fails with ClassCirculatoryError. I would like to
>>>>>> know if there is a bug in felix 1.6 code or if I need to do
>>>>>> something else to workaround this error. Please note that the
>>>>>> whole thing worked with the previous felix version 1.2.2 of
>>>>>> glassfish b43.
>>>>>>
>>>>>> Due to this failure I am not able to proceed further and not sure
>>>>>> how I can integrate JRuby monitoring code as I cant test it on v3
>>>>>> trunk.
>>>>>>
>>>>>> -vivek,
>>>>>>
>>>>>>
>>>>>>
>>>>>> [1]http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6508296
>>>>>> [2]http://www.mail-archive.com/dev@felix.apache.org/msg06806.html
>>>>>>
>>>>>>
>>>>>> Vivek Pandey wrote:
>>>>>>> There is JRuby QL failure:
>>>>>>> https://glassfish.dev.java.net/issues/show_bug.cgi?id=7648.
>>>>>>>
>>>>>>> You might recall how jruby compiler runtime is initiated by
>>>>>>> jruby container. Basically, based on where jruby install
>>>>>>> (jruby.home is), a URLClassLoader is created using the jruby
>>>>>>> install jars. This URLClassLoader is used to start of JRuby
>>>>>>> runtime by reflection.
>>>>>>>
>>>>>>>
>>>>>>> URL[] urls = findJRubyJars();
>>>>>>> ClassLoader cl = new URLClassLoader(urls,
>>>>>>> JRubyApplication.class.getClassLoader());
>>>>>>>
>>>>>>> Class<?> c =
>>>>>>> cl.loadClass("com.sun.grizzly.jruby.RubyRuntime");
>>>>>>> this.jRubyRuntime =
>>>>>>> c.getConstructor(Properties.class, String.class,
>>>>>>> String.class).newInstance(deploymentContext.getAppProps(),
>>>>>>> railsRoot, contextRoot);
>>>>>>> this.adapter = (com.sun.grizzly.tcp.Adapter)
>>>>>>> c.getMethod("getAdapter").invoke(jRubyRuntime);
>>>>>>> startJRubyGrizzlyAdapter();
>>>>>>>
>>>>>>> See method initJRubyGrizzlyAdapter() and rest of the code at:
>>>>>>> http://pastie.org/450451
>>>>>>>
>>>>>>> for some reason with b45 onward and latest v3 trunk, I see one
>>>>>>> thing that the previous v3 build b43, used to have
>>>>>>> ContentClassLoader that loaded the JRubyApplication and now in
>>>>>>> trunka dn b45, there is ModuleClassLoader. Not sure whats going
>>>>>>> on that is causing such ClassCirculatoryError.
>>>>>>>
>>>>>>>
>>>>>>> ---------
>>>>>>> java.lang.ClassCircularityError:
>>>>>>> org/jruby/lexer/yacc/RubyYaccLexer$LexState
>>>>>>> Apr 17, 2009 4:02:40 PM SEVERE: at
>>>>>>> org.jruby.lexer.yacc.RubyYaccLexer.yylex(RubyYaccLexer.java:917)
>>>>>>> ---------
>>>>>>>
>>>>>>> See the details stack trace: http://pastie.org/450344
>>>>>>>
>>>>>>> Due to this error, JRuby/Rails etc. are not working on trunk.
>>>>>>> Probably you would have some idea as to whats going on.
>>>>>>>
>>>>>>> thanks,
>>>>>>>
>>>>>>> -vivek.
>>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>>
>>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>>>>>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>