Thanks a lot Niclas, I think I'm starting to see the light now.

Just one last wish ;D 
Is there any good article/document/resource about classloading architectures? I will 
be changing the classloading architecture of a servlet container my company is 
developing and apart from some documents explaining how classloaders work in some 
servlet containers I couldn't find any "how to do it properly" document.

thanks again,

Horaci

-----Original Message-----
From: Niclas Hedhman [mailto:[EMAIL PROTECTED]
Sent: 14 November 2003 03:27
To: Avalon framework users
Subject: Re: Question about article "Developing With Apache Avalon"



Sounds like ClassLoadingMan has to jump in and set things right...

1. Class.forName() seems to have changed its definition over time. IF it is as 
the javadoc says, that it will use the classloader of the calling class, the 
only thing I can see is that there might be a performance issue. It used to 
be the System Classloader.

2. Class.forName( ,, classloader) uses the given classloader.

3. getClass().getClassLoader().loadClass() uses the same classloader as the 
one used to load the class calling.

4. The Thread.currentThread().getContextClassLoader() is (as it says) the 
classloader for the execution context, and varies.

There are no "generic advice" of what to use, and there are few subsystems 
that are absolutely accurate in the use of classloaders. For instance, Swing 
uses Thread.getContextClassLoader in some instances, and Class.forName in 
others, making Swing non-conformant to a non-standard classloading setup.


Going back to your original question/statement;

Class.forName() has been bad (assuming they have re-implemented as the 
javadocs says, since I haven't checked since 1.2) and you be better off not 
using it at all.

Whether getClass().getClassLoader() is "better" than 
Thread.currentThread().getContextClassLoader() is not an issue. It depends on 
the context.

Don't forget that the ClassLoader is not only responsible to load classes and 
resources, but it also handles the security context, and that is where the 
context classloader becomes important, WHO is executing the code that came 
from WHERE, also called the CodeSource.

The general advice is roughly like this;
1. If you are loading a class that is bundled together with the calling class, 
always use getClass().getClassLoader().

2. If you implementing containers, like Stephen is, you probably would take 
the Thread.currentThread().getContextClassLoader() in the top parent 
container, and use it as a parent to a new instance(s) of URLClassLoader, 
which you tell to load the classes in question. This also have the benefit 
that you can unload the classes later.

3. If you have a more complex setup, you basically need to draw the 
classloader hierarchy on a piece of paper, and sit down and decide which 
classes resides in which classloaders, and which CL is parent of which other 
CL. It is a messy business, but done right, you get immense powers.

4. If you want to load resources directly associated with your class, always 
use getClass().getClassLoader().

5. If you want to load resources (classes or other) that your component expect 
to be provided by the caller/using class, use the 
Thread.currentThread().getClassLoader() and specify in your component 
contract that is the case.

Anything else? Can't think of anymore use-cases...

Niclas



On Friday 14 November 2003 00:53, Horaci Macias wrote:
> "The problem with the this.getClass().getClassLoader().loadClass(String)
> is that it triggers a seach relative to the classloader in which "this"
> is defined. If "this" is in a classloader higher than the class you
> trying to load then you out of luck wheras the context classloader is
> the lowest classloader in the stack relative to your implementation."
>
> I agree. The example I was thinking about assumed that "this" and the class
> to load are in the same CL. Maybe I should have copy-pasted the text I was
> referring to:
>
> "Many Java tools internally use Class.forName(String).newInstance() to
> instantiate some part of its internal functionality. This works if the
> class's Jar is mounted at the top-level system classloader. In the case of
> many Avalon containers, the Jar in question will actually be mounted in a
> classloader at some other point in a tree of classloaders. Thus 
> Class.forName() will fail with ClassNotFoundException if running in a
> container."
>
> as the text says "to instantiate some part of its internal functionality" I
> think is talking about a class which is in the same classloader as "this".
> In this case, wouldn't Class.forName(String) and
> this.getClass().getClassLoader().loadClass(String) do the same?
>
> I also think (correct me if I'm wrong) that (in this example with "this"
> and the loaded class in the same CL)
> Thread.currentThread().getContextClassLoader().loadClass(String) would do
> the same as the two other options, as long as the Context Classloader was
> set properly before calling the tools' class. This dependence of the
> Context ClassLoader being handled properly makes me doubt about which
> option to use.
>
> thanks a lot,
>
> Horaci
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to