dev@glassfish.java.net

Re: Classloading problem

From: Jan Luehe <Jan.Luehe_at_Sun.COM>
Date: Tue, 16 Jan 2007 19:12:45 -0800

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
>