*
The moose likes Java in General and the fly likes Loading same class by two different class loader (ClassCastException) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Loading same class by two different class loader (ClassCastException)" Watch "Loading same class by two different class loader (ClassCastException)" New topic
Author

Loading same class by two different class loader (ClassCastException)

Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809
Hi,
Could anyone please explain how a ClassCastException comes during class loading.

Every class is identified in JVM by a key which is a combination of three thing...[classname, packagename, its loader] and this combination must be unique. Does it mean that when you have duplicate combination for a single class, then ClassCastException comes.

I am not able to figure out the reason behind ClassCastException at the class load time.

Thanks in advance

Naseem
[ July 19, 2006: Message edited by: Naseem Khan ]

Asking Smart Questions FAQ - How To Put Your Code In Code Tags
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

I'm not sure what's motivating your question. Here's a class that will throw a ClassCastException during classloading.



[Jess in Action][AskingGoodQuestions]
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809
I got this type of exception when I bundled my transfer object in both WAR and EJB-JAR of my application.

My transfer object class is something like this....


Here since my TransferObject class is in both WAR as well as in EJB-JAR, it will be loaded by two class loaders. Then I passed the instance of TransferObject created in WAR in EJB-JAR. There I already have one instance whose class is loaded by EJB class loader. When I call overridden equals() method on these two TransferObject instances, I get ClassCastException.

I think because the two instances are loaded by different classloader I am getting ClassCastException.

I am not sure about that and how to get the same thing by a simple java program.

Can I load same class by two different class loaders?

Here is one quote from onjava.com


we have classes M-A1 (M loaded by class loader A1) and M-A2 (M loaded by classloader A2). Imagine we also have another class, Test-A1, with a method upcastM() that looks like this:


Because the class Test is loaded by A1, its symbolic link M is also loaded by A1. So we are going to upcast a given object to M-A1. When this method is called with an instance of the class M-A1 as an argument, it will return successfully, but if it is called with an instance of M-A2, it will throw a ClassCastException because it is not the same class, according to the JVM.

[Ref: Inside Class Loaders by Andreas Schaefer]

Thanks

Naseem
[ July 18, 2006: Message edited by: Naseem Khan ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

Yes, OK. You asked about ClassCastExceptions happening during class loading, but that's not really what you're asking.

If you load the same class file twice, in two different ClassLoaders, then the two classes are indeed two different classes, and you can't cast one to the other. The solution is not to put these classes into more than one archive file; you can take them out into a single shared jar and make sure it's loaded by a common ancestor class loader.
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809

Originally posted by Ernest Friedman-Hill
Yes, OK. You asked about ClassCastExceptions happening during class loading, but that's not really what you're asking.



Thanks for your reply sir. I think the subject line is not correctly displaying my problem.

So now I am going to edit the subject line...

Now lets take a different case.



In the above code when I execute Test.main(), Test class will be loaded by System classpath classloader.

At line 2, will the same class be loaded again by loader1? I am sure whether Test class will be loaded by two class loader.

Can I get same ClassCastException by simple java program?. Well the whole point is loading same class by two different class loader and then casting one reference type in another.


Naseem
[ July 19, 2006: Message edited by: Naseem Khan ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

In your simple program, the same classloader handles everything; the class is loaded only once. The forName() call returns the same Class object from a cache.

You could reproduce the ClassCastException problem in a relatively small program, but it's not just the code, but how you deploy it that counts. Here's a recipe that would work:

1) Write a little class "Test", something like your original class with an equals() method that casts the argument to "Test". Compile it, then move Test.class to some location that is definitely NOT on your class path. This is important: if you don't do this, then you won't get the exception later.

2) Create two instances of URLClassLoader. Give each instance a constructor argument with a URL pointing to the location of Test.class. Note that now both these ClassLoaders can find Test.class, but the system classloader cannot.

3) Load the class once with each URLClassLoader to create two Class objects by using the three-argument form of Class.forName().

4) Create an instance from each Class object using newInstance(). Just store each instance in Object variables o1 and o2.

5) Call o1.equals(o2). You should then see the ClassCastException.
Chris Beckey
Ranch Hand

Joined: Jun 09, 2006
Posts: 116

There are, at least, two general ways to generate a ClassCastException under the conditions described. One is with a branched ClassLoader hierarchy, and the second is with a ClassLoader that does not preferentially delegate to its parent.
Read on for the long winded explanation ...

In a simple J2SE application (like "Hello World") there are at least three ClassLoader instances involved. In order (and order is very significant) these are:
1.) bootstrap classes,
2.) extension classes
3.) classpath (user) classes.
These form a hierarchy (parent-child relationship) where the child (higher number in the above list) class loaders delegate to their parent before trying to load a class themselves. The delegation behavior is by convention and is not enforced.
As long as this is a simple chain (one child per parent) and the contract for delegation is followed then ClassCastExceptions due to ClassLoader differences are impossible.
If the ClassLoader hierarchy branches (i.e. 2 or more children for any parent) then ClassCastExceptions may be thrown even if the class names are identical. This is the scenario illustrated in the earlier post by Mr Friedman-Hill where there are 2 instances of URLClassLoader, each a child of the classpath classloader.
Also, if a ClassLoader does not follow the convention of delegating first to its parent then the potential exists for ClassCastException due to different ClassLoader instances. The simplest way to do this would be to write a ClassLoader that loads a class before delegating to its parent, in which case it could load something that the parent already has loaded.
J2EE app servers use a ClassLoader hierarchy to enforce some security, e.g. not allowing EARs to access other EARs classes. The behavior depends on the app server. Some app servers use one ClassLoader per EAR and a child ClassLoader per WAR. Some use a sibling arrangement where a ClassLoader for a WAR delegates to a sibling classloader for an EJB-JAR.

A relavent reference from: http://java.sun.com/developer/technicalArticles/Networking/classloaders/index.html

"As of JDK 1.2, a bootstrap class loader that is built into the JVM is responsible for loading the classes of the Java runtime. This class loader only loads classes that are found in the boot classpath, and since these are trusted classes, the validation process is not performed as for untrusted classes. In addition to the bootstrap class loader, the JVM has an extension class loader responsible for loading classes from standard extension APIs, and a system class loader that loads classes from a general class path as well as your application classes.

Since there is more than one class loader, they are represented in a tree whose root is the bootstrap class loader. Each class loader has a reference to its parent class loader. When a class loader is asked to load a class, it consults its parent class loader before attempting to load the item itself. The parent in turn consults its parent, and so on. So it is only after all the ancestor class loaders cannot find the class that the current class loader gets involved. In other words, a delegation model is used."
Naseem Khan
Ranch Hand

Joined: Apr 25, 2005
Posts: 809
Thanks Friedman. Thanks Chris.

I really apreciate the effort which you have made in solving the problem.


JavaRanch rocks

Regards

Naseem
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Loading same class by two different class loader (ClassCastException)
 
Similar Threads
Difference between Compiler Error & Runtime Exception
conflict due class is having same name as well as same package structure
jvm,jre,jdk,jit
Instantiating classes in jar file used by Web project
Class cast exception