用jni封装so后,在java程序中使用时,System.load()不知道so的abs path;tem.loadLibrary(),so又不在java.library.path中。
又因为jdk的这个bug(也许不能称之为bug,http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4280189),故采用下面的workaround,力求cover所有的cases。
ref.
http://stackoverflow.com/questions/23824368/how-can-i-configure-java-library-path-at-runtime
http://stackoverflow.com/questions/24037409/set-java-library-path-for-tomcat
http://frommyplayground.com/how-to-load-native-jni-library-from-jar/
http://bbs.csdn.net/topics/390713944
private static void addLibPath(String path) throws Exception
{
try {
int i;
Field[] flds = ClassLoader.class.getDeclaredFields();
for (i = 0; i < flds.length; i++) {
if (flds[i].getName().equals("usr_paths")) break;
}
if (i == flds.length) {
throw new Exception("ClassLoader.usr_paths non-exists");
}
Field usr_paths_fld = ClassLoader.class.getDeclaredField("usr_paths");
usr_paths_fld.setAccessible(true);
String[] paths = (String[])usr_paths_fld.get(null);
for (i = 0; i < paths.length; i++) {
if (path.equals(paths[i])) return;
}
String[] new_paths = Arrays.copyOf(paths, paths.length + 1);
new_paths[new_paths.length - 1] = path;
usr_paths_fld.set(null, new_paths);
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Setting ClassLoader.usr_paths failed");
}
}
private static void loadLibFromJar(String lib_name) throws FileNotFoundException
{
String lib_fn = "lib" + lib_name + ".so";
File temp = null;
try {
temp = File.createTempFile("lib" + lib_name, ".so");
} catch (Exception e) {
e.printStackTrace();
}
if (!temp.exists()) {
throw new FileNotFoundException("File[" + temp.getAbsolutePath() + "] non-exists");
}
temp.deleteOnExit();
InputStream is = QbusProducer.class.getResourceAsStream("/" + lib_fn);
if (is == null) {
throw new FileNotFoundException("File[/" + lib_fn + "] was not found inside JAR");
}
OutputStream os = new FileOutputStream(temp);
try {
byte[] buffer = new byte[64 * 1024];
int nread;
while ((nread = is.read(buffer)) != -1) {
os.write(buffer, 0, nread);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.load(temp.getAbsolutePath());
}
static {
try {
System.load("/path/to/libmyjin.so");
} catch (Exception e) {
e.printStackTrace();
try {
addLibPath("/path/to");
System.loadLibrary("qbusjniclient");
} catch (Exception e2) {
e2.printStackTrace();
try {
loadLibFromJar("qbusjniclient");
} catch (FileNotFoundException e3) {
e3.printStackTrace();
}
}
}
}