代码之家  ›  专栏  ›  技术社区  ›  TwentyMiles

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

  •  7
  • TwentyMiles  · 技术社区  · 14 年前

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

    我想能够动态加载的dll虽然,基于哪个版本的用户想要使用。如果我打电话怎么办System.loadLibrary文件两次使用不同名称但方法签名相同的DLL?

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

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

    3 回复  |  直到 14 年前
        1
  •  4
  •   time4tea    14 年前

    我必须在生产环境中这样做,在sunjvm上它是坚如磐石的。

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

    我不建议你这样做,除非你真的不得不。。。但它确实有用。

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

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

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

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

    那种事。。。。。

        2
  •  1
  •   Wouter Coekaerts    14 年前

    我不知道在windows中如何加载DLL的细节,但我的直觉告诉我,同时加载重叠的库肯定不安全。但如果你先卸下第一个,可能会。

        3
  •  1
  •   sfjac    9 年前

    这是不安全的,执行起来相当混乱。对于不同版本的dll,可能有不同的类加载器。您必须确保类加载器是垃圾收集的,以确保dll已被卸载。(见 Java JNI - DLL Unloading )

    过去,我们通过编写一个轻量级java中介进程来解决这个问题,该进程处理用户的请求,并使用请求的dll版本创建一个新的子java进程。当用户请求不同的版本时,中介会关闭现有的子版本,并生成具有不同库路径的新版本。这种方法很有效。唯一的缺点是启动新jvm所需的时间,但只有当您频繁地请求版本切换时,这一点才会明显。