[ajug-members] FW: [Fwd: multiple jar versionsfor one application]
Chris Abney
Chris.Abney at theice.com
Thu May 1 16:44:29 EDT 2008
Here is a great answer from Jed Casper. Thnaks Jed
Chris Abney
BTW. If you don't have that book, here is the excerpt from the web:
http://www.informit.com/articles/article.aspx?p=1187967
-----Original Message-----
From: Jed [mailto:jcasper at ga-1.com]
Sent: Thursday, May 01, 2008 4:31 PM
To: Chris Abney
Subject: [Fwd: multiple jar versionsfor one application]
Chris,
Everyone keeps responding that you can't do it, but I disagree. That is
to say that I don't think you have to change the package or class name
or anything about the code that you are using, and that may not be under
your control to make changes to at the source code level.
For instance, when I deploy webapps, I have the exact same code in the
exact same named jar file go into the WEB-INF/lib folder for each one.
This code has a static initializer to create a singleton instance of a
class. When the class is loaded the static initializer creates the
singleton and each webapp has it's own singleton instance, even though
all webapps are running in a single JVM instance, because the code for
each webapp is loaded with a different classloader. To match your
problem description further, the code for the singleton objects could be
different (like different versions of the same thing) and you can see
that each webapp has it's own instance and it's own version of the code,
even though the jar file may be named the same and the name of the class
is exactly the same.
Here is an excerpt from Core Java book .... ISBN is 0-13-111826-9
"It may surprise you, however, that you can have two classes in the same
virtual machine that have the same class and package name. A class is
determined by its full name and the class loader. This technique is
useful for loading code from multiple sources. For example, a browser
uses separate instances of the applet class loader class for each web
page. This allows the virtual machine to separate classes from different
web pages, no matter what they are named."
So, all you have to do is load each class with it's own classloader.
ClassLoader loader = new MyClassLoader(); Class c =
loader.loadClass(name);
where MyClassLoader overrides findClass() to get the bytes for the class
file and pass them to defineClass().
Since the loadClass method will delegate to the parent class loader
first, you will need to make sure it cannot find one of your conflicting
classes. Take it off the classpath. Now your classloader will load and
define one of the conflicting classes and it will essentially become a
separate type than the one loaded by the system class loader....all
running in a single JVM. You can operate on your loaded class via
reflection on the Class object. The classloader essentially acts as a
another level of namespace scope.
You might consider using two classloaders for each or your conflicting
classes (and everything they reference); two separate "class"-paths,
that your classloaders use, where everthing is the same except for the
conflicting classes will have different code.
public class myClass { //Put myClass on the classpath
:
public void doIt() {
ClassLoader loader = new MyClassLoaderDaddyBee(); //loads classes
from path A - not on formal classpath
Class daddyBee =
loader.loadClass(org.chrisabney.functors.WorkerBee);
ClassLoader loader2 = new MyClassLoaderSonBee(); //load classes
from path B - not on formal classpath
Class sonBee = loader.loadClass(org.chrisabney.functors.WorkerBee);
Method daddyMethod = daddyBee.getMethod("doIt", null);
Method sonMethod = sonBee.getMethod("doIt", null);
daddyMethod.invoke(daddyBee.newInstance(), null); //The old boring
way
sonMethod.invoke(sonBee.newInstance(), null); //The new wacky way
}
}
Good luck. With everyone saying it can't be done, maybe I'm the one
who's wrong ; )
Jed Casper
More information about the ajug-members
mailing list