(点击上方公众号,可快速关注)
来源:伯乐在线专栏作者 - 望天
链接:http://android.jobbole.com/85213/
点击 → 了解如何加入专栏作者
接上文
public static synchronized void load(String... paths) {
if(paths != null && paths.length != 0) {
String[] javaLibPath = paths;
int arr$ = paths.length;
int len$;
String path;
for(len$ = 0; len$ arr$; ++len$) {
String i$ = javaLibPath[len$];
path = (new File(i$)).getName();
if(loaded.contains(path)) {
log.info("already loaded " + i$);
return;
}
}
javaLibPath = System.getProperty("java.library.path").split(File.pathSeparator);//这里获得windows下path对应的路径,是个字符串数组
String[] var11 = paths;
len$ = paths.length;
for(int var12 = 0; var12 len$; ++var12) {
path = var11[var12];
log.config("JNI LIB = " + path);
String[] extracted = javaLibPath;
int len$1 = javaLibPath.length;
for(int i$1 = 0; i$1 len$1; ++i$1) {
String libPath = extracted[i$1];
File file = (new File(libPath, path)).getAbsoluteFile();//这里根据path路径和dll的名称拼成一个文件路径,下面检查这个文件是否存在,如果不存在,拼下一个文件路径,如果存在,就加载这个dll
log.finest("checking " + file);
if(file.exists() && file.isFile() && liberalLoad(file, path)) {
return;
}
}
File var13 = extract(path);
if(var13 != null && liberalLoad(var13, path)) {
return;
}
}
throw new ExceptionInInitializerError("unable to load from " + Arrays.toString(paths));
} else {
throw new ExceptionInInitializerError("invalid parameters");
}
}
其实这段代码本来我没有看太懂,但是架不住调试功能强大,运行一次,加断点,看看内容怎么变化,就知道是什么意思了.
这里假设我的windows下Path环境变量设置为:”D:\Python\Python35\Scripts\;D:\Program Files\Java\jdk1.7.0_15\bin;C:\WINDOWS;D:\BLAS;”,那么javaLibPath的内容就会是这四个组成的字符串数组.接下来取出来第一个,和dll名称(netlib-native_system-win-x86_64.dll)一起拼成一个文件路径”D:\Python\Python35\Scripts\netlib-native_system-win-x86_64.dll”,接下来检查这个路径是否是文件,如果不是,就会继续拼下一个,直到拼出”D:\BLAS\netlib-native_system-win-x86_64.dll”,然后我的dll文件确实放在这里,程序就会加载.
现在我们找到对应的dll文件,这里为netlib-native_system-win-x86_64.dll,然后放在D:\BLAS\这个位置,把D:\BLAS加入path变量,然后重启Intellij(这一步不一定需要,大家自己尝试),让它重新读取path值.
重新运行下Test里的main函数,然后运行结果竟然还是如上的错误,额,是我们刚才的分析都是错误了么?
2.dll库的依赖和依赖查找
我们在跳进加载dll的地方,看看究竟是哪里错了:
private static boolean liberalLoad(File file, String name) {
try {
log.finest("attempting to load " + file);
System.load(file.getAbsolutePath());
log.info("successfully loaded " + file);
loaded.add(name);
return true;
} catch (UnsatisfiedLinkError var6) {
//这里捕获到一个异常,说Can't find dependent libraries.
log.log(Level.FINE, "skipping load of " + file, var6);
String tmpdir = System.getProperty("java.io.tmpdir");
if(tmpdir != null && tmpdir.trim().length() > 2 && file.getAbsolutePath().startsWith(tmpdir)) {
log.log(Level.FINE, "deleting " + file);
try {
file.delete();
} catch (Exception var5) {
log.info("failed to delete " + file);
}
}
return false;
} catch (SecurityException var7) {
log.log(Level.INFO, "skipping load of " + file, var7);
return false;
} catch (Throwable var8) {
throw new ExceptionInInitializerError(var8);
}
}
这里我们捕获到一个异常,说 D:\BLAS\netlib-native_system-win-x86_64.dll: Can’t find dependent libraries.
原来如此我们的库还需要一些依赖库,这些依赖库没有找到.但是我们怎么知道这个库依赖于哪些库呢?哪些是已经有的,哪些是没有的?这里推荐一个工具,叫PEStudio,可以查看dll文件或exe文件依赖于哪些库:
这里显示了netlib-native_system-win-x86_64.dll依赖于哪些库,其中liblapack3.dll和libblas3.dll是我们需要找到了.其实到这一步,问题就算解决了,参见OpenBlas的官网,这些文件都可以很轻松的下载到,就是要注意首先需要知道你要的是32位还是64位,其次所有dll需要是统一的,不能部分32,部分64. 谢谢曲奇饼的提醒, 这里需要注意的还有jdk的版本, 在64位系统下, 应该使用64的jdk, 大家注意尝试.
这里是我用PEStudio找到的依赖关系:
至此,问题圆满解决.
=========================
最后,把在win10 64位系统下成功运行的库文件放在这:
csdn:http://download.csdn.net/detail/u201011221/9355487
baiduyun: http://pan.baidu.com/s/1jGO5waE
关注「安卓开发精选」
看更多精选安卓技术文章
↓↓↓