使用loadLibrary加载dll

时间:2015-05-04 15:21:33

标签: java java-native-interface 64-bit environment-variables

我目前正在维护一个Java通信库,它通过JNI包装某些dll提供的功能。在某些时候,在Java中,我需要加载JNI包装器来转发我的请求,最后调用本机库。目前,这是通过调用

来完成的
System.loadLibrary("MyLibrary");

如上所述here,如果MyLibrary位于java.library.path之内,则应始终找到java.library.path。目前,我的C:\Program Files\Java\jdk1.8.0_45\bin; C:\Windows\Sun\Java\bin; C:\Windows\system32; C:\Windows; C:\Program Files\ImageMagick-6.9.0-Q16; C:\ProgramData\Oracle\Java\javapath; C:\Windows\system32; C:\Windows; C:\Windows\System32\Wbem; C:\Windows\System32\WindowsPowerShell\v1.0\; C:\Program Files\Microsoft SQL Server\110\Tools\Binn\; C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\; C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0\; C:\texlive\2014\bin\win32; C:\MyFolder\Common32; C:\MyFolder\Common64; C:\Program Files (x86)\Microsoft Team Foundation Server 2012 Power Tools\; C:\Program Files (x86)\Microsoft Team Foundation Server 2012 Power Tools\Best Practices Analyzer\;. 似乎包含一些Java特定文件夹以及%PATH%环境变量中指定的所有目录:

MyLibrary

我现在的问题是,即使C:\MyFolder\Common64;放在loadLibrary中,上述UnsatisfiedLinkError来电也会产生System32,我似乎无法理解原因。但是当我将它放入load文件夹时,或者我在完全指定路径时调用System.load("C:\\MyFolder\\Common64\\MyLibrary.dll"); 时会发现它:

java.library.path

我尝试使用herehere给出的答案中建议的sys_path技巧在运行时使用System.setProperty("java.library.path", "C:\\MyFolder\\Common64\\" ); Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" ); fieldSysPath.setAccessible( true ); fieldSysPath.set( null, null ); System.loadLibrary("MyLibrary"); 。以下工作完美无瑕:

java.library.path

因此,如果我用自定义路径替换整个java.library.path属性,则会成功加载dll。但是,这不是理想的行为,因为我想通过将正确的目录添加到%PATH%来动态地找到dll。此外,将我的自定义路径添加到String curJavaLibraryPath = System.getProperty("java.library.path"); System.setProperty("java.library.path", curJavaLibraryPath + ";C:\\MyFolder\\Common64\\" ); ,如此

C:\MyFolder\Common32\

也行不通。

目前我正在尝试在Win7 64位计算机上进行此项工作。我的dll也被编译为x64,如果这是相关的。

当我在x86模式下编译我的Java库并将相应的JNI dll复制到"Hola @toni e @sophea estoy muy contento". 并将该目录添加到%PATH%时,一般过程完美无缺。

1 个答案:

答案 0 :(得分:0)

显然,loadLibrary() Documentation已经设法欺骗了我一点。如果UnsatisfiedLinkError表示

  

UnsatisfiedLinkError - 如果库不存在。

因此,我显然认为loadLibrary()在任何时候都无法看到我指定的库。但是,并非如此,因为此异常也意味着它发现相应的库存在错误(与VM不兼容)的位数。

据我所知,您可以做的唯一检查是确定您具有哪个UnsatisfiedLinkError,这是为了分解异常所包含的错误消息。我最终做的是:

try
{
    System.setProperty(JAVA_LIBPATH_PROPNAME, libpath);  
    ForceReloadLibraryPath();
    System.loadLibrary("AdsToJava");        
}
catch (UnsatisfiedLinkError ex)
{
    // We simply did not find the dll
    if (ex.getMessage().equals("no MyLibrary in java.library.path")) {

        // Just alert that nothing was found

    } else if ( (ex.getMessage().endsWith("Can't load IA 32-bit .dll on a AMD 64-bit platform")) || 
                (ex.getMessage().endsWith("Can't load AMD 64-bit .dll on a IA 32-bit platform")) ) {

        // Extract the path at which the dll whith the wrong bitness was found 
        // and remove it from the search path and try again
    }
}

你显然也可以在调用loadLibrary之前预先检查搜索路径,但是这种方法也适用于用户在搜索路径上复制dll的情况,我认为这是最强大的选项。