Java Classloader - how to reference different versions of a jar
Asked Answered
L

5

19

This is a common problem. I'm using 2 libraries A.jar and B.jar and these depend on different versions of the same jar.
Let's say that at runtime I need THIS.x.x.x.jar

MY.jar   
     -> A.jar -> THIS.1.0.0.jar
     -> B.jar -> C.jar -> THIS.5.0.0.jar

I can compile the specific jar (A.jar/B.jar) against its dependency but at runtime I've to load only 1 version. Which one?
Loading only 1 dependency (the latest version) means that my code will probably throw runtime exceptions if the libraries are not Backward Compatible (are there Backward Compatible libraries out there?).

Anyway I know that something like OSGi can fix this issue.
I'm wondering what's the old way to fix this kind of problems...

Thanks a lot

Leola answered 12/10, 2009 at 9:28 Comment(1)
Is it possible to achieve this?How OSGi helps?We are again introducing a depenency on OSGi which is an overhead in typical product software development (especially for embedded )Sharpnosed
N
7

"Old way" you mentioned (and the one OSGI certainly uses under the hood) is to install your own ClassLoader for both branches of your dependencies. That's how, for instance, application servers are able to run both older and newer versions of the same application inside the same JVM.

Read about classloader hierarchy.

In your setup, the tricky part is the joint point, where classes from both branches meet. Neither branches can use classes loaded into another one. The way to make it work is to make sure only classes loaded by boot classloader (JRE classes) or classloader of MY.jar are passed down to both branches.

November answered 12/10, 2009 at 15:18 Comment(0)
L
4

OSGi can fix this problem. An OSGi bundle is nothing more than a jar with additional metadata detailing versions. A bundle has a version number, and will detail version numbers (or ranges) of dependent jars.

Take a look at this introductory Javaworld article for more information.

To solve this without OSGi means having to ensure manually that you compile and run with compatible jars. As you've discovered that's not necessarily a trivial task. Since jars don't necessarily identify their versions, the only sure way to do this to record/compare checksums or signatures.

Loco answered 12/10, 2009 at 9:50 Comment(0)
U
1

Many libraries are backward compatible. But not all..


The old way is to try to depend from only one version.

It is probably safer to compile both with the same version (latest).
At least you get compile-time errors, instead of runtime errors.

If needed, you can modify a little bit your library that works with the old dependency...
This would require access to the source...


Please note that compile-time compatibility will not guarantee correct runtime behavior either. It is one step, then you can:

  • read the WhatsNew file for the new version of the jar
  • look on the Internet for users reporting compatibility problems
  • write JUnits
  • compare the codes in both jars
Upswing answered 12/10, 2009 at 9:46 Comment(0)
M
1

As mentioned by KLE, the default approach is to depend on the newer version. There is no guarantee, but most of the time this works. Probably the best way (while being a bloated one) is using OSGI to get over it.

Mozza answered 12/10, 2009 at 9:51 Comment(0)
A
1

To refer a basic "oldway" implementation checkout https://github.com/atulsm/ElasticsearchClassLoader

This provides an approach to handle non-backward compatible versions of elasticsearch client usage.

Altis answered 13/2, 2016 at 19:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.