我目前正在维护一个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
我尝试使用here和here给出的答案中建议的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%时,一般过程完美无缺。
答案 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的情况,我认为这是最强大的选项。