Question

I've just solved another *I-though-I-was-using-this-version-of-a-library-but-apparently-my-app-server-has-already-loaded-an-older-version-of-this-library-*issue (sigh).

Does anybody know a good way to verify (or monitor) whether your application has access to all the appropriate jar-files, or loaded class-versions?

Thanks in advance!

[P.S. A very good reason to start using the OSGi module architecture in my view!]

Update: This article helped as well! It gave me insight which classes JBoss' classloader loaded by writing it to a log file.

Was it helpful?

Solution

If you happen to be using JBoss, there is an MBean (the class loader repository iirc) where you can ask for all classloaders that have loaded a certain class.

If all else fails, there's always 'java -verbose:class' which will print the location of the jar for every class file that is being loaded.

OTHER TIPS

If you've got appropriate versions info in a jar manifest, there are methods to retrieve and test the version. No need to manually read the manifest.

java.lang.Package.getImplementationVersion() and getSpecificationVersion() and isCompatibleWith() sound like they'd do what you're looking for.

You can get the Package with this.getClass().getPackage() among other ways.

The javadoc for java.lang.Package doesn't give the specific manifest attribute names for these attributes. A quick google search turned it up at http://java.sun.com/docs/books/tutorial/deployment/jar/packageman.html

In the current version of Java, library versioning is a rather wooly term that relies on the JAR being packaged correctly with a useful manifest. Even then, it's a lot of work for the running application to gather this information together in a useful way. The JVm runtime gives you no help whatsoever.

I think your best bet is to enforce this at build time, using dependency management tools like Ivy or Maven to fetch the correct versions of everything.

Interestingly, Java 7 will likely include a proper module versioning framework for precisely this sort of thing. Not that that helps you right at this moment,

I don't think there is a good way to check that. And I'm not sure you want to do that. What you need to do is get familiar with your app-server's class loading architecture, and understand how that works.

A simplified explanation of how it works is: an EJB or a web-app will first look for a class or a resource in libraries declared in its own module (ejb-jar or war). if the class is not found there, the class loader forwards the request to the its parent class loader which is either a declared dependency (usualy an ejb) or the the application class loader which is responsible to load libraries and resources declared in the ear package. If the class or the resource is still not found the request is forwarded to the app server which will look in its own classpath.

This being said, you should remember that a Java EE module (web-app, ejb) will always load classes from a jar that is in the nearest scope. For example if you package log4j v1 in the war file, log4j v2 at ear level and you put log4j v3 in your app-server's class path, the module will use the jar in its own module. take that away and it'll use the one at ear level. take that out and it will use the one in the app-server's classpath. Things get more tricky when you have complex dependencies between modules.

Best is to put application global libraries at ear level.

There must be a better way than the way I do it, but I tend to do this in a very manual way.

  1. Every Jar must have it's version number in the file name (if it doesn't change it's name).
  2. each application has it's own classpath.
  3. There must be a reason to start using an updated Jar (new version). Don't just change because it is available, change because it gives you functionality that you need.
  4. Each release must include all Jars that are needed.
  5. I keep a Version class that knows the list of Jars it needs (this is coded into the source file) and can be checked at runtime against the list of Jars in the classpath.

As I said, it is manual, but it works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top