是否可以在Java中加载相同DLL的不同版本?

Twe*_*les 8 java java-native-interface

我有一个与一组第三方库交互的JNI库,系统上可能有多个版本的第三方库.对于第三方库的每个版本,出于可比性原因,我必须重新编译JNI代码.现在我通过加载具有特定名称的DLL来解决这个问题,如果版本发生更改,我会更改JNI接口DLL的名称,以便正确的版本具有正确的加载名称.

我希望能够根据用户想要使用的版本动态加载dll.如果我在具有不同名称但具有相同方法签名的DLL上调用System.loadLibrary两次会发生什么?

System.loadLibrary("JNIv1");
// Same code compiled against a different third party version
System.loadLibrary("JNIv2");
Run Code Online (Sandbox Code Playgroud)

我只需要一次使用其中一个版本,所以如果旧版本不再可访问就没问题.

是否可以使用相同的方法签名加载两个不同版本的DLL而无需重新启动程序?

tim*_*tea 4

这是可能的,事实上它得到了完全的支持并且工作得非常出色。

我必须在生产环境中执行此操作,并且在 sun JVM 上它坚如磐石。

基本上,如果您从不同的类加载器加载库,那么它将加载该库的不同副本。就这么简单。

我不建议这样做,除非你真的必须这样做......但它确实有效。

作为替代方案,根据您的具体要求,您可以将其从进程中删除,并在客户端和不同服务器之间使用一个简单的协议(例如使用 jetty/xstream/httpclient 或 netty),每个服务器都有不同的协议已加载 dll 版本。

本质上这涉及到你编写一个类加载器

public class MyClassLoader extends URLClassLoader {

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

然后您安排使用相关的类加载器加载类的实现......

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();

    }
}
Run Code Online (Sandbox Code Playgroud)

那种事......