简体   繁体   中英

Loading two classes in different JARs

I got two classes with the same package in different JARs. Until the previous version, both classes were identical, so i had no issues in loading them. Now, one of them has a new method added and if I want to access it, not only should I import the class with that package, i also need to make sure the jar with the correct class comes first in the classpath.

ie javac -classpath "%classpath%;a.jar;b.jar" MyClasses..

where a.jar has the class with my new method.

Now, how do i ensure this when my app goes to production, where it's deployed as an EAR file, with all the libraries under WEB-INF/lib?

How do I know which jar gets the preference over the other? Is it the alphabetical order like a.jar is given the first preference over b.jar?

I've read this safe-class-imports-from-jar-files thread and got to know about writing a custom classloader, but is there a better simpler solution that? Cos I'm just going to access this method in that whole JAR in this current project and writing a classloader seems a bit overkill.

And please don't ask me "Why the hell same class with same package in different JARs?" It's absolutely out of my control and it'll take some time to get this corrected.

Environment details: IBM WAS 6.1 on their 1.5 Java.

Please ask me more questions, if I don't make much sense. Thanks in advance!

As far as I know, the order of jars being loaded from WEB-INF/lib is arbitrary - I asked a similar question about JBOSS and got the reply ( from RedHat ) that it depends on the order that java.io.File.listFiles() returns them in ( and that is not a guaranteed order ).

A custom classloader would be an option, but have you considered repackaging the jars - removing the duplicated classes?

You can try to change the startup script of your server and specify the jar with the correct class in the bootclasspath by using java -Xbootclasspath .... Otherwise there is no guarantee which one of the 2 jars will load up first.

Websphere allows you to specify the order in which classloaders of a particular application are inquired when searching for a class (the classloaders are hierarchically structured, from the topmost that loads JRE classes, down to classloader loading classes in your WAR).

During deployment of an app, you can specify if the order of inquiring the classloaders when searching for a class. There are two modes - Parent first (ie query the topmost classloader first) and parent last (query the app classloader first). This can be specified on both EAR and WAR level.

Packaging the duplicated jars to different locations in the app (eg one to EAR's classpath, the other to WAR's WEB-INF/lib) and setting the classloader orderING apropriately may solve your problem. However, if both your JARs have to be on the same level (eg WEB-INF/lib), then there's no way to specify which one will be used when loading the duplicated class.

The order of the JARs in one application is likely to be alphabetical but the order of applications might not. Additionally, it depends on how the server handles classloading, ie whether it replaces existing classes or skips the new ones.

Although you already stated that, I'd still like to give that advice: Having the same class in multiple JARs deployed in one application (which could happen with versioned jars, for example) is always a bad idea. Your better off to invest the time to fix that instead of trying to mess with class loading.

This might come out to be pretty vague but I do remember resolving this issue a long time back by messing around with the WAS admin console for that given application and rearranging the relevant JAR files using their web UI. Not sure if this is an acceptable step in your case but worth a try in case everything else fails.

assuming you have some control over the deployment, fix the classloading yourself. combine the problematic jars yourself by unzipping them in reverse loading order into the same directory and then re-zipping into a new jar. then deploy the app with the new combo jar. no duplicate classes, problem solved.

or, just delete the dupe classes from the jars before deploying.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM