|
View:
New views
4 Messages
—
Rating Filter:
Alert me
|
|
|
FW: [Fwd: multiple jar versionsfor one application]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@...] 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 _______________________________________________ ajug-members mailing list ajug-members@... http://www.ajug.org/mailman/listinfo/ajug-members |
|
|
Re: FW: [Fwd: multiple jar versionsfor one application]Chris,
I think I'm confused as to what problem you are trying to solve. From your original post, it seemed as if you wanted polymorphic behavior out of some classes, but I could be wrong. Are you truly looking to use two different versions of the same class (from different jar files) who's source you don't have access to? Or are you implementing these classes and you want two different behaviors based on which type is instantiated? If it is the former, then I think Jed gave you the answer you were looking for (and a lot of us have some crow to eat), but if it is the latter, then there are much simpler methods for achieving this than involving class loaders (explicitly). Gene On Thu, May 1, 2008 at 4:44 PM, Chris Abney <Chris.Abney@...> wrote: > 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@...] > 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 > > > > > > _______________________________________________ > ajug-members mailing list > ajug-members@... > http://www.ajug.org/mailman/listinfo/ajug-members > _______________________________________________ ajug-members mailing list ajug-members@... http://www.ajug.org/mailman/listinfo/ajug-members |
|
|
Re: FW: [Fwd: multiple jar versionsfor one application]Jed, we've been saying all along that it can't be done _in the same classloader_. It is possible to do via different class loaders, although, unless Chris is developing or working with framework internals, I doubt this is what he wants to do. I'm just repeating myself (twice!) ;)
Multiple classloaders are _rarely_ ever used by application developers. I'm not saying it doesn't happen, but if you do need to go through that exercise, it should be noted as a red flag that something isn't right, and that further inspection into alternatives are a good idea before you go down that road. Unfortunately, Chris didn't provide much of a back story as to what his restrictions are or what exactly he's trying to achieve, so we couldn't go beyond telling him the basics: that its not possible unless you (or a framework you use) utilize(s) different classloaders.
Cheers, Les On Thu, May 1, 2008 at 4:44 PM, Chris Abney <Chris.Abney@...> wrote: Here is a great answer from Jed Casper. Thnaks Jed _______________________________________________ ajug-members mailing list ajug-members@... http://www.ajug.org/mailman/listinfo/ajug-members |
|
|
Re: FW: [Fwd: multiple jar versionsfor one application]I'm w/ Les on this one. Jed's example is great for separate apps but my understanding of your problem is that you wanted to do this in the _same_ app which assumes 1 classloader. When you start introducing more classloaders, you'd be amazed of the fun and excitement you will achieve in debugging. I think Jim has a good idea w/ letting a factory manage the version differences. If you have each version implement a common interface, your factory (or dependency injector) can hand you back the version you need based on arguments and your client code is none the wiser of the implementation. On 5/1/08, Les Hazlewood <les@...> wrote: Jed, we've been saying all along that it can't be done _in the same classloader_. It is possible to do via different class loaders, although, unless Chris is developing or working with framework internals, I doubt this is what he wants to do. I'm just repeating myself (twice!) ;) _______________________________________________ ajug-members mailing list ajug-members@... http://www.ajug.org/mailman/listinfo/ajug-members |
| Free Forum Powered by Nabble | Forum Help |