I have 2 separate Web applications that load the exact same JAR file
JF1 - which contains class X.
I am running Tomcat ver 5.0.28 with JDK 1.4.03
I also have an in-memory Object cache that is available to both WebApp
A and WebApp B. That is, the one instance of this cache is available
to both applications.
Web Application A loads this JAR file JF1, creates an instance of X and
puts this instance into the cache.
WebApplication B starts up, and loads this JAR file JF1, then after
startup is finished, retrieves the instance of class X via the method:
'public Object getInstance(final String sKey)'
When WebApp B tries to cast this Object back to an instance of class X,
I get a ClassCastException. I do a System.out.println of
'obj.getClass().getName()' on the Object and it is in fact an instance
of Class X. Altho the JVM is not recognizing it as such.
Both Web Applications use the same exact JAR file JF1 (a 3rd party JAR
file).
Does anyone have any ideas how to overcome this problem?
The way the applications are constructed, I cannot simply take JAR file
JF1 and drop it into shared/lib because one of the Web Applications is
un-modifiable to me, and I doubt my sys-admin would agree to the
change.
John C. Bollinger - 24 Jan 2006 04:13 GMT
> I have 2 separate Web applications that load the exact same JAR file
> JF1 - which contains class X.
[quoted text clipped - 26 lines]
> un-modifiable to me, and I doubt my sys-admin would agree to the
> change.
Then you're probably out of luck. Classes loaded by different
ClassLoaders are different classes, even if they have exactly the same
bytecode read from exactly the same file. As do most application
servers, Tomcat assigns each web application its own ClassLoader for
loading the classes specific to it (i.e. those referenced via
WEB-INF/lib or WEB-INF/classes). That is why you are getting
ClassCastExceptions.
You possibly could work around the problem if the objects in your cache
are Serializable. You could then convert them from one ClassLoader's
copy of the class to the other by serializing them to memory and then
deserializing them. This is far from a general solution, however, as
(1) it doesn't work for objects that aren't serializable;
(2) it may exhibit surprising and/or undesired semantics, as it *copies*
the original object; and
(3) the overhead may negate the usefulness of caching the objects in the
first place
For Tomcat 5, dropping the Jar into shared/lib and making both webapps
use that version is exactly what you want to do. To prevent the webapps
from loading the classes via their own local ClassLoaders, you need to
make sure that the jar is only accessible from shared/lib. Details of
Tomcat's class loading behavior can be found among the Tomcat docs:
http://tomcat.apache.org/tomcat-5.0-doc/class-loader-howto.html
Bottom line: bake your sysadmin some cookies, and see whether you can
persuade him to move the jar to shared/lib.

Signature
John Bollinger
jobollin@indiana.edu