You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by Leo Sutic <le...@inspireinfrastructure.com> on 2001/11/22 09:40:09 UTC

DefaultLogTargetFactoryManager

Line 86:
                logTargetFactory =
                    (LogTargetFactory)
this.getClass().getClassLoader().loadClass( factoryClass ).newInstance();

This leads to some classloader issues. Is there a reason for this or can the
context class loader be used instead?

/LS


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: ClassLoader rule-of-thumb? (Re: DefaultLogTargetFactoryManager)

Posted by Peter Donald <pe...@apache.org>.
On Thu, 22 Nov 2001 22:31, Jeff Turner wrote:
> Hi Leo,
>
> On Thu, Nov 22, 2001 at 09:40:09AM +0100, Leo Sutic wrote:
> > Line 86:
> >                 logTargetFactory =
> >                     (LogTargetFactory)
> > this.getClass().getClassLoader().loadClass( factoryClass ).newInstance();
> >
> > This leads to some classloader issues. Is there a reason for this or can
> > the context class loader be used instead?
>
> If I may take the opportunity to ask.. is the general rule that one
> should prefer the context classloader to that of the code's class?

Depends on where you expect the code to be run. If you expect your code to 
run in some sort of container (ie servlet, ejb, phoenix, whatever) then it is 
expected that the container will setup ContextClassLoader correctly. 

In a container context there is no guarentee that the loader used for current 
class come from any particular hierarchy. Thats why servlets and EJBs can 
intermix their ClassLoaders somewhat promiscuosly and apps still run (because 
they use the ContextClassLoader).

If your are not running in a container then there is no hard and fast rules 
but most environments would expect that Class.forName() (which uses the 
caller classloader) or getClass().getClassLoader().loadClass() to work.

> Ie, Thread.currentThread().getContextClassLoader() instead of
> this.getClass().getClassLoader()?
>
> I notice that Cocoon2's ClassUtils always returns the context CL. I'm
> guessing that the context CL is more flexible, because the caller may
> belong to a less "primitive" classloader than the excalibur code. Does
> that sound right?

That works because in most cases people are probably using Cocoon2 in a 
servlet. It would be nicer if Cocoon2 did  not rely on ContextClassLoader and 
loaded from getClass().getClassLoader() if ContextClassLoader was not set.

> Eg, say that avalon-excalibur.jar is in Tomcat 3.2's $TOMCAT_HOME/lib.
> Your class in WEB-INF/lib tries to set the factory class mentioned above
> to something else in WEB-INF/lib, then the context CL will work, and the
> class CL will fail?

correct. Though webapp classloaders slightly violate the normal ClassLoader 
rules, as of 2.3 it is recomended that they search the local repositories 
before searching parent classloaders os if you also had excalibur in you 
WEB-INF/lib then it would work .... at least on some containers who follow 
recomendation ;)

-- 
Cheers,

Pete

*------------------------------------------------*
| Trying is the first step to failure.           |
|   So never try, Lisa  - Homer Jay Simpson      |
*------------------------------------------------*


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: ClassLoader rule-of-thumb? (Re: DefaultLogTargetFactoryManager)

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> -----Original Message-----
> From: Jeff Turner [mailto:jeff@socialchange.net.au]
> Sent: den 22 november 2001 12:31
> To: Avalon Developers List
> Subject: ClassLoader rule-of-thumb? (Re: DefaultLogTargetFactoryManager)
> 
> 
> Hi Leo,
> 
> On Thu, Nov 22, 2001 at 09:40:09AM +0100, Leo Sutic wrote:
> > 
> > Line 86:
> >                 logTargetFactory =
> >                     (LogTargetFactory)
> > this.getClass().getClassLoader().loadClass( factoryClass 
> ).newInstance();
> > 
> > This leads to some classloader issues. Is there a reason for 
> this or can the
> > context class loader be used instead?
> 
> If I may take the opportunity to ask.. is the general rule that one
> should prefer the context classloader to that of the code's class?

Yes. See http://www.javageeks.com/Papers/ClassForName/index.html for why.

/LS


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


ClassLoader rule-of-thumb? (Re: DefaultLogTargetFactoryManager)

Posted by Jeff Turner <je...@socialchange.net.au>.
Hi Leo,

On Thu, Nov 22, 2001 at 09:40:09AM +0100, Leo Sutic wrote:
> 
> Line 86:
>                 logTargetFactory =
>                     (LogTargetFactory)
> this.getClass().getClassLoader().loadClass( factoryClass ).newInstance();
> 
> This leads to some classloader issues. Is there a reason for this or can the
> context class loader be used instead?

If I may take the opportunity to ask.. is the general rule that one
should prefer the context classloader to that of the code's class?

Ie, Thread.currentThread().getContextClassLoader() instead of
this.getClass().getClassLoader()?

I notice that Cocoon2's ClassUtils always returns the context CL. I'm
guessing that the context CL is more flexible, because the caller may
belong to a less "primitive" classloader than the excalibur code. Does
that sound right?

Eg, say that avalon-excalibur.jar is in Tomcat 3.2's $TOMCAT_HOME/lib.
Your class in WEB-INF/lib tries to set the factory class mentioned above
to something else in WEB-INF/lib, then the context CL will work, and the
class CL will fail?

I am woefully ignorant of classloaders, so any explanations appreciated
:) Otherwise, a rule of thumb would do just fine.


--Jeff

> /LS

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: DefaultLogTargetFactoryManager

Posted by Peter Donald <pe...@apache.org>.
On Sat, 24 Nov 2001 00:11, Leo Sutic wrote:
> The API clearly states that the context class loader is not null.
>
> UNLESS THE CONTEXT CLASS LOADER IS THE BOOTSTRAP CLASS LOADER.
>
> So, my mistake here.
>
> So what I propose is:
>
>   Thread.currentThread ().getContextClassLoader ().loadClass (className);
>
>           <==============Transforms into===================>
>
>   Class.forName (className, true, Thread.currentThread
> ().getContextClassLoader ());
>
> This works even if Thread.currentThread ().getContextClassLoader () == null
> as stated in the API spec:
>
>   If the parameter loader is null, the class is loaded through the
> bootstrap class loader.

okay - that makes more sense to me - which is precisely why I like to first 
check by ContextClassLoader (via above) and then check the using calling 
class loader. Rarely is any of the needed classes in the bootstrap 
classloader but it is likely that they are in the calling classloader. Thus I 
would still use

Class clazz = null;

try
{
  clazz = Class.forName (className, true, 
      Thread.currentThread().getContextClassLoader ());
}
catch( final ClassNotFoundException cnfe )
{
  clazz = Class.forName( className );
}

if at all possible. This maybe partially because I am used to having apps 
work in both hosted (ala servlets/blocks/ejbs) and unhosted environments 
(normal apps).

> Someday I'll get around to submit a patch to Cocoon's ClassUtils about
> this...

;)

-- 
Cheers,

Pete

----------------------------------
   "Don't play dumb with me. 
I happen to be an expert at that" 
           - Maxwell Smart
----------------------------------

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: DefaultLogTargetFactoryManager

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> -----Original Message-----
> From: Peter Donald [mailto:peter@apache.org]
> Sent: den 22 november 2001 21:35
> To: Avalon Developers List
> Subject: Re: DefaultLogTargetFactoryManager
> 
> 
> On Fri, 23 Nov 2001 00:13, Leo Sutic wrote:
> > Java API for Thread.getContextClassLoader ():
> >
> > "Returns the context ClassLoader for this Thread. The context 
> ClassLoader
> > is provided by the creator of the thread for use by code running in this
> > thread when loading classes and resources.
> >
> > If not set, the default is the ClassLoader context of the parent Thread.
> >
> > The context ClassLoader of the primordial thread is typically set to the
> > class loader used to load the application."
> >
> > So that should be "never", as I understand it. Do you have any examples
> > when getContextClassLoader () == null?
> 
> oh - I thought it started out as null for some reason.

The API clearly states that the context class loader is not null.

UNLESS THE CONTEXT CLASS LOADER IS THE BOOTSTRAP CLASS LOADER.

So, my mistake here.

So what I propose is:

  Thread.currentThread ().getContextClassLoader ().loadClass (className);

          <==============Transforms into===================>

  Class.forName (className, true, Thread.currentThread ().getContextClassLoader ());

This works even if Thread.currentThread ().getContextClassLoader () == null as stated in the API spec:

  If the parameter loader is null, the class is loaded through the bootstrap class loader. 

Someday I'll get around to submit a patch to Cocoon's ClassUtils about this...

/LS



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: DefaultLogTargetFactoryManager

Posted by Peter Donald <pe...@apache.org>.
On Fri, 23 Nov 2001 00:13, Leo Sutic wrote:
> Java API for Thread.getContextClassLoader ():
>
> "Returns the context ClassLoader for this Thread. The context ClassLoader
> is provided by the creator of the thread for use by code running in this
> thread when loading classes and resources.
>
> If not set, the default is the ClassLoader context of the parent Thread.
>
> The context ClassLoader of the primordial thread is typically set to the
> class loader used to load the application."
>
> So that should be "never", as I understand it. Do you have any examples
> when getContextClassLoader () == null?

oh - I thought it started out as null for some reason. Even then I have seen 
applications where it is null, and it would suck if your app started throwing 
NPEs or failing because of this. It would also suck for any applications that 
create ClassLoaders but don't set the ContextClassLoader (or set it to 
another value) because they would fail.

-- 
Cheers,

Pete

------------------------------------------------------
 Mark Twain: "In the real world, the right thing never
happens in the right place at the right time. It is 
the task of journalists and historians to rectify 
this error."
------------------------------------------------------

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: DefaultLogTargetFactoryManager

Posted by Leo Sutic <le...@inspireinfrastructure.com>.

> -----Original Message-----
> From: Peter Donald [mailto:peter@apache.org]
> Sent: den 22 november 2001 13:55
> To: Avalon Developers List
> Subject: Re: DefaultLogTargetFactoryManager
> 
> 
> On Thu, 22 Nov 2001 23:59, Leo Sutic wrote:
> > > -----Original Message-----
> > > From: Peter Donald [mailto:peter@apache.org]
> > > Sent: den 22 november 2001 13:37
> > > To: Avalon Developers List
> > > Subject: Re: DefaultLogTargetFactoryManager
> > >
> > >
> > > How about using the contextClassLoader first and then if that
> > > fails using the
> > > classes classloader ?
> >
> > I don't see in what situations that would help. All I see is a jumble of
> > class loaders. I think we should stick to the context class loader
> > throughout the code.
> 
> And when the ContextClassLoader is not set ?

Java API for Thread.getContextClassLoader ():

"Returns the context ClassLoader for this Thread. The context ClassLoader is provided by the creator of the thread for use by code running in this thread when loading classes and resources. 

If not set, the default is the ClassLoader context of the parent Thread. 

The context ClassLoader of the primordial thread is typically set to the class loader used to load the application."

So that should be "never", as I understand it. Do you have any examples when getContextClassLoader () == null?
 
/LS


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: DefaultLogTargetFactoryManager

Posted by Peter Donald <pe...@apache.org>.
On Thu, 22 Nov 2001 23:59, Leo Sutic wrote:
> > -----Original Message-----
> > From: Peter Donald [mailto:peter@apache.org]
> > Sent: den 22 november 2001 13:37
> > To: Avalon Developers List
> > Subject: Re: DefaultLogTargetFactoryManager
> >
> >
> > How about using the contextClassLoader first and then if that
> > fails using the
> > classes classloader ?
>
> I don't see in what situations that would help. All I see is a jumble of
> class loaders. I think we should stick to the context class loader
> throughout the code.

And when the ContextClassLoader is not set ?

-- 
Cheers,

Pete

*----------------------------------------------*
| The best defense against logic is ignorance. |
*----------------------------------------------*

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: DefaultLogTargetFactoryManager

Posted by Leo Sutic <le...@inspireinfrastructure.com>.
> -----Original Message-----
> From: Peter Donald [mailto:peter@apache.org]
> Sent: den 22 november 2001 13:37
> To: Avalon Developers List
> Subject: Re: DefaultLogTargetFactoryManager
> 
> 
> How about using the contextClassLoader first and then if that 
> fails using the 
> classes classloader ?

I don't see in what situations that would help. All I see is a jumble of class loaders. I think we should stick to the context class loader throughout the code.

/LS



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: DefaultLogTargetFactoryManager

Posted by Peter Donald <pe...@apache.org>.
On Thu, 22 Nov 2001 23:36, giacomo wrote:
> On Thu, 22 Nov 2001, Leo Sutic wrote:
> > Line 86:
> >                 logTargetFactory =
> >                     (LogTargetFactory)
> > this.getClass().getClassLoader().loadClass( factoryClass ).newInstance();
> >
> > This leads to some classloader issues. Is there a reason for this or can
> > the context class loader be used instead?
>
> Sure, my fault not having used it. Go ahead and change it.

How about using the contextClassLoader first and then if that fails using the 
classes classloader ?

-- 
Cheers,

Pete

-----------------------------------------------
   "You can't depend on your eyes when your 
   imagination is out of focus." -Mark Twain 
-----------------------------------------------

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: DefaultLogTargetFactoryManager

Posted by giacomo <gi...@apache.org>.
On Thu, 22 Nov 2001, Leo Sutic wrote:

>
> Line 86:
>                 logTargetFactory =
>                     (LogTargetFactory)
> this.getClass().getClassLoader().loadClass( factoryClass ).newInstance();
>
> This leads to some classloader issues. Is there a reason for this or can the
> context class loader be used instead?

Sure, my fault not having used it. Go ahead and change it.

Giacomo


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>