为什么记录?
Java 可以通过System.load()与System.loadLibrary()加载动态库。
问题一 :loadLibrary()加载有libname参数指定的系统库。将库映射到实际系统库的方法取决于系统。load() 以指定的文件名加载代码文件。文件名必须是绝对路径。使用opencv时,需要系统能够work every where,所以需要使用load()方法。将dll或者so文件打包到jar下,并不能直接使用,需要将文件写到临时文件中。
问题二 :动态文件加载一遍之后,bundle卸载重装,但karaf并没有重新启动,到日志bundle再次运行后出现文件已经加载,再次加载出错的问题。解决办法是在bundle停止运行或者卸载的时候,将动态文件释放。
1. 将jar包中的文件写到临时文件夹
//BIN_LIB为JAR包中存放DLL的路径
//getResourceAsStream以JAR中根路径为开始点
public static String getLib(String libName, String type) throws IOException {
BufferedInputStream reader = null;
FileOutputStream writer = null;
String systemType = System.getProperty("os.name");
String libExtension = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
String libFullName = libName + libExtension;
String nativeTempDir = System.getProperty("java.io.tmpdir");
File extractedLibFile = new File(nativeTempDir + File.separator + libFullName);
InputStream in = LibUtil.class.getResourceAsStream("/libs/" + libFullName);
if (!extractedLibFile.exists()) {
try {
if (in == null)
in = LibUtil.class.getResourceAsStream(libFullName);
LibUtil.class.getResource(libFullName);
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();
}
}
return extractedLibFile.toString();
}
2. 卸载或释放动态链文件
// libName:动态文件全路径
public static synchronized void unloadNativeLibs(String libName) {
try {
ClassLoader classLoader = LibUtil.class.getClassLoader();
Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
field.setAccessible(true);
Vector<Object> libs = (Vector<Object>) field.get(classLoader);
Iterator it = libs.iterator();
while (it.hasNext()) {
Object object = it.next();
Field[] fs = object.getClass().getDeclaredFields();
for (int k = 0; k < fs.length; k++) {
if (fs[k].getName().equals("name")) {
fs[k].setAccessible(true);
String dllPath = fs[k].get(object).toString();
if (dllPath.endsWith(libName)) {
Method finalize = object.getClass().getDeclaredMethod("finalize");
finalize.setAccessible(true);
finalize.invoke(object);
list.add(libName);
}
}
}
}
} catch (Throwable th) {
th.printStackTrace();
}
}