正常情况下, xxx.class.getResourceAsStream(lib) 这样就可以获取到了。但是我的是在JFrame的初始化中的, 所以需要Thread.currentThread().getContextClassLoader().getResourceAsStream(lib); 这样来获取。 这个坑 找了蛮久才找到解决方案记录下。
嗯 看了一些解决方案,1、把库跟jar包一起拷贝打包 2、放入指定路径 添加环境变量 通过环境变量来获取库路径等等 终究还是比较麻烦的。
经过测试发现 本文的方案 还是没有最终解决这个问题 手里还有别的事 先放下了后面再研究
private synchronized static void copyLib(String libFullName, String arch_libfile_suffix) throws IOException {
InputStream in = null;
BufferedInputStream reader = null;
FileOutputStream writer = null;
File f = new File(".");
String libs[] = { libFullName, libFullName.replace(arch_libfile_suffix, ".c"), libFullName.replace(arch_libfile_suffix, ".h") };
for(int i = 0;i<libs.length;++i){
File extractedLibFile = new File(f + File.separator + libs);
if(!extractedLibFile.exists()){
//打包进jar中后, 可以用zip软件打开jar文件 看看你需要调用的dll或者so 在jar中的路径就是这个lib的值
String lib = libs.replace("lib" + File.separatorChar, "");
// String lib = libs;
System.out.println("lib = " + lib);
try {
// “/”代表Jar包的根目录
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(lib);
// 踩过的坑 这些方式都没能够成功获取到。 这是因为我的获取是在UI线程中的。
// MD5.class.getResourceAsStream("/" + libs);
// MD5.class.getClassLoader().getResourceAsStream("/" + libs);
// MD5.class.getResource(libFullName);
System.out.println(" getResourceAsStream == " + lib);
reader = new BufferedInputStream(in);
writer = new FileOutputStream(extractedLibFile);
byte[] buffer = new byte[1024];
while (reader.read(buffer) > 0){
writer.write(buffer);
buffer = new byte[1024];
}
} catch (IOException e){
e.printStackTrace();
} finally {
if(in!=null)
in.close();
if(writer!=null)
writer.close();
}
}
}
}
这种方案 经过测试在mac上面是可行的 但是在windows上面 总是拷贝lib失败 报 IOException 异常. 先记录 后面再解决
还有下面这种解决方案,来自https://www.cnblogs.com/FlyingPuPu/p/7598098.html
就是把Jar 当作zip文件遍历,找出需要加载的lib 然后拷贝到指定路径再进行加载
/**
* 加载项目下的native文件,DLL或SO
*
* @param dirPath 需要扫描的文件路径,项目下的相对路径
* @throws IOException
* @throws ClassNotFoundException
*/
public synchronized static void loader(String dirPath) throws IOException, ClassNotFoundException {
Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(dirPath);
// 获取操作系统类型
String systemType = System.getProperty("os.name");
String systemArch = System.getProperty("os.arch");
// 获取动态链接库后缀名
String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
while (dir.hasMoreElements()) {
URL url = dir.nextElement();
String protocol = url.getProtocol();
if ("jar".equals(protocol)) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
JarFile jarFile = jarURLConnection.getJarFile();
// 遍历Jar包
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
String entityName = jarEntry.getName();
if (jarEntry.isDirectory() || !entityName.startsWith(dirPath)) {
continue;
}
if (entityName.endsWith(ext)) {
loadJarNative(jarEntry);
}
}
} else if ("file".equals(protocol)) {
File file = new File(url.getPath());
loadFileNative(file, ext);
}
}
}
|