Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to load different versions of the same DLL in Java?

I have a JNI library that interacts with a set of third party libraries, and there may be more than one version of the third party library on the system. For each version of the third party library, I have to re-compile the JNI code for comparability reasons. Right now I deal with this by loading a DLL with a specific name, and if the version changes I change the names of the JNI interface DLLs so that the correct one for the version has the right name to get loaded.

I'd like to be able to dynamically load the dll though, based on which version the user wants to use. What happens if I call System.loadLibrary twice on DLLs with different names but the same method signatures?

System.loadLibrary("JNIv1");
// Same code compiled against a different third party version
System.loadLibrary("JNIv2");

I only need to use one of the versions at a time, so it's fine if the old version is no longer accessable.

Is it possible to load two different versions of a DLL with the same method signatures without re-starting the program?

like image 220
TwentyMiles Avatar asked Sep 09 '10 16:09

TwentyMiles


1 Answers

It is possible and in fact it is totally supported and works brilliantly.

I have had to do this in a production environment and on a sun JVM it is rock solid.

Basically, if you load the library from a different classloader, then it will load a different copy of the library. Its as simple as that.

I wouldn't recommend doing this unless you really have to... but it does work.

As an alternative, depending on your specific requirements, you could just make it out of process, and have a simple protocol (using say jetty/xstream/httpclient, or netty) between the client and the different servers, each of which has a different dll version loaded.

Essentially this involves you writing a classloader

public class MyClassLoader extends URLClassLoader {

   protected String findLibrary(String libName) {
         if ( libName.equals("mylib.dll")) {
              return "full/path/to/library";
         }
         else {
              super.findLibrary(libName);
         }
   }
}

Then you arrange to load the implementation of your class using the relevant classloader...

public interface Implementation {

}

public class ImplementationLookerUpper {

    Classloader v1 = new MyClassloader(version1);
    Classloader v2 = new MyClassloader(version2);


    public Implementation implementationUsingVersion(Version someversion) {

             Classloader classloader = pickCorrectClassLoaderForVersion(someVersion);

            return (Implementation) classloader.loadClass(RealImplementation.class.getName()).newInstance();

    }
}

That kind of thing.....

like image 197
time4tea Avatar answered Nov 10 '22 00:11

time4tea