dev@glassfish.java.net

Re: Classloading problem

From: Ashish Sahni <Ashish.Sahni_at_Sun.COM>
Date: Wed, 17 Jan 2007 10:12:27 -0800

Hi Jan/Siva,
That worked ! Thanks much for the detailed responses.

-Ashish

Sivakumar Thyagarajan wrote:

> Hi Ashish,
>
> Jan is correct. It appears that JRuby uses the default ClassLoader
> constructor[1] and thus uses the system classloader as the parent. The
> system classloader in glassfish has just bare bootstrapping jar
> [appserv-launch.jar] in its path and hence all the libraries placed at
> install-dir/lib is not available for this JRuby classloader.
>
> While hunting further, I also found out someone else raising a similar
> issue in JRuby[2] and a corresponding jira issue[3]. You may want to
> update/vote for the jira issue :)
>
> >> 2. By setting system-classpath attribute in java-config to contain the
> >> list of all the jars in $gf/lib, I was
> >> able workaround the error below. Not very elegant though. So the
> question
> Until that fix is done, the workaround is to use the system-classpath
> attribute in GlassFish.
>
> Thanks
> --Siva.
> [1]
> http://svn.jruby.codehaus.org/browse/jruby/trunk/jruby/src/org/jruby/internal/runtime/methods/InvocationMethodFactory.java?r=2702#l47
>
> [2]
> http://www.nabble.com/Current-JRuby-broken-in-JavaWebStart-t3010943.html
> [3] http://jira.codehaus.org/browse/JRUBY-439
>
>
> Jan Luehe wrote:
>
>> Hi Ashish,
>>
>> there's a great classloader overview at
>>
>> https://glassfish.dev.java.net/javaee5/docs/DG/beade.html
>>
>> Your classloader is created like this:
>>
>> public static class InvokeClassLoader extends ClassLoader {
>> public static final InvokeClassLoader INSTANCE = new
>> InvokeClassLoader();
>>
>> public Class define(String name, byte[] code) throws
>> ClassFormatError {
>> return defineClass(name,code,0,code.length);
>> }
>> }
>>
>> Notice how java.lang.ClassLoader defines 2 constructors: one that
>> takes a
>> (delegation) parent classloader, and one that takes no args. When you
>> use the latter (as InvokeClassLoader does), the (delegation) parent
>> of the
>> newly constructed classloader will default to the system classloader.
>>
>> As you can see from the GlassFish classloader diagram, the system
>> classloader
>> will be too high up in the delegation chain, because it knows nothing
>> about
>> classes in <domain-dir>/lib.
>>
>> I think InvokeClassLoader should define a constructor that takes a
>> ClassLoader parent argument, and implement this constructor by calling
>>
>> super(parent).
>>
>> Then, when org.jruby.internal.runtime.methods.InvocationMethodFactory
>> instantiates InvokeClassLoader, it should pass
>>
>> InvocationMethodFactory.class.getClassLoader()
>>
>> as the parent argument, which should return the Common Classloader
>> (since org.jruby.* is available in <domain-dir>/lib), which will have
>> access
>> to any classes in <domain-dir>/lib.
>>
>> Can you try this out?
>>
>>
>> Jan
>>
>>
>> Ashish Sahni wrote On 01/16/07 04:51 PM,:
>>
>>> More info/questions:
>>>
>>> 1. GlassFish does startup when the system property
>>> com.sun.aas.useNewClassLoader is set to false
>>>
>>> 2. By setting system-classpath attribute in java-config to contain
>>> the list of all the jars in $gf/lib, I was
>>> able workaround the error below. Not very elegant though. So the
>>> question
>>> I suppose is - is this the only way to get the system-classloader to
>>> load classes under $gf/lib ? Or
>>> any other way of circumventing the issue ?
>>>
>>> 3. My initial thought was that the library was extending from
>>> java.lang.ClassLoader incorrectly a
>>> maybe better suited by using Thread.currentClassLoader() to define
>>> new classes. However, on taking
>>> a closer look at the source/error - the library is trying to
>>> define a class from an array of bytes -
>>> there doesn't seem to be any way other than (extend and) use
>>> java.lang.ClassLoader's define
>>> method (which is protected) or is there ? What is the GlassFish's
>>> recommended solution to this question -
>>> dynamically-defining-classes-from-byte-array ?
>>>
>>> Thanks
>>> Ashish
>>>
>>> Ashish Sahni wrote:
>>>
>>>> Oleksiy Stashok wrote:
>>>>
>>>>> Hi,
>>>>> as I understand from stacktrace seems you actually don't have
>>>>> lifecycle module, but instead your runtime is being initialized by
>>>>> Grizzly, is it correct?
>>>>
>>>>
>>>>
>>>>
>>>> That's correct. I assumed from the following snippet that the last
>>>> classloader to be the lifecycle-classloader
>>>> and hence the explanation in my prior email.
>>>> ...
>>>> at
>>>> com.sun.enterprise.web.PEWebContainerLifecycle.onStartup(PEWebContainerLifecycle.java:71)
>>>>
>>>> at
>>>> com.sun.enterprise.server.ondemand.ServiceGroup.startLifecycleServices(ServiceGroup.java:266)
>>>>
>>>> at
>>>> com.sun.enterprise.server.ondemand.WebServiceGroup.startLifecycleServices(WebServiceGroup.java:211)
>>>>
>>>> ...
>>>>
>>>>> Where actually you put your libraries with org.jruby.*? Is it in
>>>>> GF/lib?
>>>>
>>>>
>>>>
>>>>
>>>> Yes.
>>>>
>>>> Thanks
>>>> Ashish
>>>>
>>>>>
>>>>> WBR,
>>>>> Alexey.
>>>>>
>>>>> Ashish Sahni wrote:
>>>>>
>>>>>> Hi Folks,
>>>>>> As you can see from the stack trace below I'm trying to run a
>>>>>> lifecycle module which
>>>>>> (within a lib) tries to use its own
>>>>>> classloader(InvocationMethodFactory$InvokeClassLoader which
>>>>>> extends from java.lang.ClassLoader) to define a class
>>>>>> (org/jruby/internal/runtime/methods/FullInvocationMethod) but fails.
>>>>>> I understand why it fails but am wondering what do to get past
>>>>>> the issue ...
>>>>>> Is there a switch with which the jars/classes in
>>>>>> $GLASSFISH_HOME/lib are loaded
>>>>>> via system(or is it bootstrap) classloader as opposed to
>>>>>> glassfish's common classloader
>>>>>> so that java.lang.ClassLoader finds the missing class ? Or any
>>>>>> other suggestions to get past the issue ?
>>>>>>
>>>>>> THanks
>>>>>> Ashish
>>>>>>
>>>>>>
>>>>>> at java.lang.ClassLoader.defineClass1(Native Method)
>>>>>> [#|2007-01-12T15:51:23.334-0800|WARNING|sun-appserver9.1|javax.enterprise.system.stream.err|_ThreadID=13;_ThreadName=Thread-5;_RequestID=51301bc0-d958-4ab1-83c5-3d81c7b7d66e;|java.lang.NoClassDefFoundError:
>>>>>> org/jruby/internal/runtime/methods/FullInvocationMethod
>>>>>> at java.lang.ClassLoader.defineClass1(Native Method)
>>>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
>>>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
>>>>>> at
>>>>>> org.jruby.internal.runtime.methods.InvocationMethodFactory$InvokeClassLoader.define(InvocationMethodFactory.java:50)
>>>>>>
>>>>>> at
>>>>>> org.jruby.internal.runtime.methods.InvocationMethodFactory.endCall(InvocationMethodFactory.java:104)
>>>>>>
>>>>>> at
>>>>>> org.jruby.internal.runtime.methods.InvocationMethodFactory.getMethod(InvocationMethodFactory.java:158)
>>>>>>
>>>>>> at
>>>>>> org.jruby.internal.runtime.methods.InvocationMethodFactory.getFullMethod(InvocationMethodFactory.java:168)
>>>>>>
>>>>>> at
>>>>>> org.jruby.runtime.builtin.meta.AbstractMetaClass.definePrivateMethod(AbstractMetaClass.java:263)
>>>>>>
>>>>>> at
>>>>>> org.jruby.runtime.builtin.meta.ObjectMetaClass$ObjectMeta.initializeClass(ObjectMetaClass.java:84)
>>>>>>
>>>>>> at
>>>>>> org.jruby.runtime.builtin.meta.ObjectMetaClass.initializeClass(ObjectMetaClass.java:103)
>>>>>>
>>>>>> at org.jruby.Ruby.initCoreClasses(Ruby.java:632)
>>>>>> at org.jruby.Ruby.init(Ruby.java:570)
>>>>>> at org.jruby.Ruby.getDefaultInstance(Ruby.java:252)
>>>>>> at
>>>>>> org.jruby.javasupport.JavaEmbedUtils.initialize(JavaEmbedUtils.java:53)
>>>>>>
>>>>>> at
>>>>>> com.sun.grizzly.rails.RubyObjectPool.initializeRubyRuntime(RubyObjectPool.java:134)
>>>>>>
>>>>>> at
>>>>>> com.sun.grizzly.rails.RubyObjectPool.start(RubyObjectPool.java:116)
>>>>>> at
>>>>>> com.sun.grizzly.rails.RailsSelectorThread.initializeRubyRuntime(RailsSelectorThread.java:106)
>>>>>>
>>>>>> at
>>>>>> com.sun.grizzly.rails.RailsSelectorThread.initEndpoint(RailsSelectorThread.java:75)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.web.connector.grizzly.GrizzlyHttpProtocol.init(GrizzlyHttpProtocol.java:212)
>>>>>>
>>>>>> at
>>>>>> org.apache.coyote.tomcat5.CoyoteConnector.initialize(CoyoteConnector.java:1590)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.web.connector.coyote.PECoyoteConnector.initialize(PECoyoteConnector.java:760)
>>>>>>
>>>>>> at org.apache.catalina.startup.Embedded.start(Embedded.java:921)
>>>>>> at
>>>>>> com.sun.enterprise.web.WebContainer.start(WebContainer.java:858)
>>>>>> at
>>>>>> com.sun.enterprise.web.PEWebContainer.startInstance(PEWebContainer.java:747)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.web.PEWebContainerLifecycle.onStartup(PEWebContainerLifecycle.java:71)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.ServiceGroup.startLifecycleServices(ServiceGroup.java:266)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.WebServiceGroup.startLifecycleServices(WebServiceGroup.java:211)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.WebServiceGroup.start(WebServiceGroup.java:60)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.ServiceGroup$1.run(ServiceGroup.java:180)
>>>>>>
>>>>>> at java.security.AccessController.doPrivileged(Native Method)
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.ServiceGroup.startChildren(ServiceGroup.java:177)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.MainServiceGroup.start(MainServiceGroup.java:45)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.ServerEntryListenerImpl.notifyEntry(ServerEntryListenerImpl.java:72)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.entry.ServerEntryHelper.sendEvent(ServerEntryHelper.java:62)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ondemand.entry.ServerEntryHelper.generatePortEntryContext(ServerEntryHelper.java:43)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ss.ASSocketService.generateEntryContext(ASSocketService.java:279)
>>>>>>
>>>>>> at
>>>>>> com.sun.enterprise.server.ss.ASSocketService$EntryPointThread.run(ASSocketService.java:525)
>>>>>>
>>>>>> |#]
>>>>>>
>>>>>> [#|2007-01-12T15:51:23.408-0800|WARNING|sun-appserver9.1|javax.enterprise.system.container.web|_ThreadID=13;_ThreadName=Thread-5;_RequestID=51301bc0-d958-4ab1-83c5-3d81c7b7d66e;|org/jruby/internal/runtime/methods/FullInvocationMethod|#]
>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>>
>>>>>> 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
>>>
>>
>> ---------------------------------------------------------------------
>> 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
>