ClassLoader questions

Hi,

I am trying to understand the mechanisms that stand behind the concept of ClassLoader and

how this i working in different scenarios. I have collected some questions where I am unsure.

So maybe someone with the neccessary knowledge can give me some enlightenment. ;-)

- Basic ClassLoaders work from top to bottom. I.e. first the base class loader is used to find the requested class along the runtime environment (rt.jar) the next is used to find it along the lib/ext directory of the used JVM and the next is used to find the requested class along the classpath.

- This order will be used by a standard java application, but if I like I can change this order as I like with the consequences it brings.

- It seems that the ClassLoader from the Apache Tomcat server, that serves as a Servlet container is working different. It tries to find classes in WEB-INF/classes and or WEB-INF/lib. Is there a certaini sequence (classes before lib ? or vice versa?)

- If I try to find a class in a jar file that is not located in the above directories (neither classpath, nor WEB-INF/classes or WEB-INF/lib) I need to write my own ClassLoader.

- I have created a jar file which contains only one class which implements one interface that can be found along the classpath.

- If I try to test this in a JUnit test everything is working as I have expected. (My JUnit instantiates myClassLoader which first looks up along rt.jar by using the base ClassLoader; doesn't find my class is looking along lib/ext etc. etc until is is using myClassLoader which is looking in my jar and finds my requested class which implements an interface that can be found along the classpath.

- If I pack all this code inside a servlet it is not working as I expected. It seems that my class is found as in my given example above, but it seems that the interface that is implemented by my class is not been found along the classpath. So I assume that I need to take care of something else.

- My Classloader extended from ClassLoader but I know that a servlet has a different one. Is it possible at all that my class can be loaded with my ClassLoader where the interface that is implemented by my class is loaded by the servlet's classloader? I remember somebody saying that identical classes loaded by different classloaders result in different classes, because the classloader is always part of the name of the loaded class .

I know that this is a lot of stuff. But maybe someone can help me with that.

Thanks & Regards

Poncho

[2594 byte] By [Poncho1975a] at [2007-11-26 14:09:49]
# 1

> Hi,

> I am trying to understand the mechanisms that stand

> behind the concept of ClassLoader and

> how this i working in different scenarios. I have

> collected some questions where I am unsure.

> So maybe someone with the neccessary knowledge can

> give me some enlightenment. ;-)

>

> - Basic ClassLoaders work from top to bottom. I.e.

> first the base class loader is used to find the

> requested class along the runtime environment

> (rt.jar) the next is used to find it along the

> lib/ext directory of the used JVM and the next is

> used to find the requested class along the

> classpath.

> - This order will be used by a standard java

> application, but if I like I can change this order as

> I like with the consequences it brings.

>

> - It seems that the ClassLoader from the Apache

> Tomcat server, that serves as a Servlet container is

> working different. It tries to find classes in

> WEB-INF/classes and or WEB-INF/lib. Is there a

> certaini sequence (classes before lib ? or vice

> versa?)

>

> - If I try to find a class in a jar file that is not

> located in the above directories (neither classpath,

> nor WEB-INF/classes or WEB-INF/lib) I need to write

> my own ClassLoader.

> - I have created a jar file which contains only one

> class which implements one interface that can be

> found along the classpath.

> - If I try to test this in a JUnit test everything is

> working as I have expected. (My JUnit instantiates

> myClassLoader which first looks up along rt.jar by

> using the base ClassLoader; doesn't find my class is

> looking along lib/ext etc. etc until is is using

> myClassLoader which is looking in my jar and finds my

> requested class which implements an interface that

> can be found along the classpath.

> - If I pack all this code inside a servlet it is not

> working as I expected. It seems that my class is

> found as in my given example above, but it seems that

> the interface that is implemented by my class is not

> been found along the classpath. So I assume that I

> need to take care of something else.

> - My Classloader extended from ClassLoader but I know

> that a servlet has a different one. Is it possible at

> all that my class can be loaded with my ClassLoader

> where the interface that is implemented by my class

> is loaded by the servlet's classloader? I remember

> somebody saying that identical classes loaded by

> different classloaders result in different classes,

> because the classloader is always part of the name of

> the loaded class .

>

> I know that this is a lot of stuff. But maybe someone

> can help me with that.

> Thanks & Regards

> Poncho

The main issue with "basic" classloaders is hierarchy. Classloaders try to load clases in a hierchical way. Before loading a class it checks werther its ancestors have loaded the class already.

In a "basic" java application there are the boot classloader, the "endorsed" classloader and the system classloader (classpath).

In a J2EE there are more classloaders. You need to consider the packaging of your application and the dependencies.There is lot of information regarding classloading in Tomcat and other J2EE app servers. Servlet specification states that web application classloader should check WEB-INF/classes first but only if its ancestors haven't done it already.

What do you need exactly?

david327a at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 2

Hi David327

My aim is to send jar files to a running servlet. The servlet should store

the jar file in a folder and then tries to load a special class from that jar

through its class loader.

All classes that are in such a jar file and that will be loaded implement

a simple interface having only one method. This method will be called afterwards.

My first try was to store the jar in WEB-INF/lib but each time I put somethin

into the WEB-INF/lib folder during runtime the servlet gets unloaded, which

is afaik correct. In addition I thought it not very wise to put my jars into that folder.

Second try was to write an own ClassLoader that extends WebappClassLoader. The class from the jar file could be loaded but while

checking dependencies the exception was thrown that the interface could not be found.

So to bring it to a point:

How can I make a servlet that is loading a class from a jar file by demand without unloading its context.

Regards

Poncho

Poncho1975a at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 3

> My first try was to store the jar in WEB-INF/lib but

> each time I put somethin

> into the WEB-INF/lib folder during runtime the

> servlet gets unloaded, which

> is afaik correct.

Are you using the same jar that the servlet is in?

> How can I make a servlet that is loading a class from

> a jar file by demand without unloading its context.

The servlet needs to use a class loader an manage it appropriately.

jschella at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 4

> - If I pack all this code inside a servlet it is not

> working as I expected. It seems that my class is

> found as in my given example above, but it seems that

> the interface that is implemented by my class is not

> been found along the classpath. So I assume that I

> need to take care of something else.

>

And exactly how did you set up the classpath so that the interface class is on it?

jschella at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 5

> Hi David327

> My aim is to send jar files to a running servlet. The

> servlet should store

> the jar file in a folder and then tries to load a

> special class from that jar

> through its class loader.

> All classes that are in such a jar file and that will

> be loaded implement

> a simple interface having only one method. This

> method will be called afterwards.

> My first try was to store the jar in WEB-INF/lib but

> each time I put somethin

> into the WEB-INF/lib folder during runtime the

> servlet gets unloaded, which

> is afaik correct. In addition I thought it not very

> wise to put my jars into that folder.

This behaviour depends on container implementation.

> Second try was to write an own ClassLoader that

> extends WebappClassLoader. The class from the jar

> file could be loaded but while

> checking dependencies the exception was thrown that

> the interface could not be found.

> So to bring it to a point:

> How can I make a servlet that is loading a class from

> a jar file by demand without unloading its context.

> Regards

> Poncho

If portability is not an issue you should try own container api. But the main point is "hierarchy", but not "inheritance". You should create a custom classloader whose ancestor would be your servlet classloader (something like servletContext.getClass().getClassLoader()). This has nothing to do with extending parent classloader.

david327a at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 6

Well, thanks for all the replies and tips.

I have found a solution which almost does what I want but more to that "almost" in the end.

I have written an own ClassLoader which is taking jar files and loads classes from inside those jar files which are located in a specified folder. In order to resolve dependencies like implemented interfaces or extended super classes which are not part of the jar file I passed the already existing ClassLoader from my servlet to my own ClassLoader, because those interfaces and superclasses can be found along the servlets classpath. That is fine solution I think (well, at least as long somebody convinces me from the opposite). It should also be possible to move the complete app to another AppContainer because I dont rely on any Tomcat specific classes.

The only thing that remains (and now comes the "almost" ) is the goal to allow unloading of already exisiting classes that have been loaded by my ClassLoader. So far I have seen that it is not enough to remove all references to my instantiated Classes and to remove the Class Types from the internal cache of my ClassLoader but as I have understood I need to "reload" my own ClassLoader completely.

Let's see what happens next. ;-)

Thanks & Regards

Poncho

Poncho1975a at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 7

So folks,

I have just finished the last test.

It seems to be fine to reinstantiate my own ClassLoader in order to unload a class. I have although some small doubts as I am not 100% sure of what I am

doing.

So are there any concerns by reinstantiating my ClassLoader or is fine doing so?

Poncho1975a at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 8

> So folks,

> I have just finished the last test.

> It seems to be fine to reinstantiate my own

> ClassLoader in order to unload a class.

Technically...

To load a new class you must have a new instance of a class loader.

The 'unloading' only occurs when the GC collects the 'old' class loader instance.

In normal functionality to do a reload one drops all the clas instances and then drops the reference to the class loader instance. Then creates a new loader and then creates new instances of the classes. Proxies are often used so that one can be sure that users of the class to be reloaded do not retain ownership of the older (real) classes.

jschella at 2007-7-8 1:57:00 > top of Java-index,Java HotSpot Virtual Machine,Specifications...