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]
