我加载了放在./lib
中的外部库。这两个解决方案是否设置java.library.path等效?
执行jar时在控制台中设置路径:
java -Djava.library.path=./lib -jar myApplication.jar
在加载库之前在代码中设置路径:
System.setProperty("java.library.path", "./lib");
如果他们等同,为什么在第二个解决方案中Java可以找不到库而第一个可以?
如果不是,有没有办法在代码中设置路径?
答案 0 :(得分:49)
虽然没有详细记录,但就java.library.path
方法而言,System.loadLibrary()
系统属性是“只读”属性。这是一个reported bug但它被Sun关闭而不是被修复。问题是JVM的ClassLoader在启动时读取此属性一次然后缓存它,不允许我们以后以编程方式更改它。除System.setProperty("java.library.path", anyVal);
方法调用外,行System.getProperty()
无效。
幸运的是,有人posted a workaround on the Sun forums。不幸的是,该链接不再有效,但我找到了the code on another source。以下是您可以用来解决无法设置java.library.path
系统属性的代码:
public static void addDir(String s) throws IOException {
try {
// This enables the java.library.path to be modified at runtime
// From a Sun engineer at http://forums.sun.com/thread.jspa?threadID=707176
//
Field field = ClassLoader.class.getDeclaredField("usr_paths");
field.setAccessible(true);
String[] paths = (String[])field.get(null);
for (int i = 0; i < paths.length; i++) {
if (s.equals(paths[i])) {
return;
}
}
String[] tmp = new String[paths.length+1];
System.arraycopy(paths,0,tmp,0,paths.length);
tmp[paths.length] = s;
field.set(null,tmp);
System.setProperty("java.library.path", System.getProperty("java.library.path") + File.pathSeparator + s);
} catch (IllegalAccessException e) {
throw new IOException("Failed to get permissions to set library path");
} catch (NoSuchFieldException e) {
throw new IOException("Failed to get field handle to set library path");
}
}
警告:这可能不适用于所有平台和/或JVM。
答案 1 :(得分:48)
一般来说,两种方法都具有相同的净效果,因为系统属性java.library.path
设置为值./lib
。
但是,某些系统属性仅在特定时间点进行评估,例如JVM的启动。 如果 java.library.path
属于这些属性(并且您的实验似乎表明了这一点),那么使用第二种方法除了在将来调用{{1 }}
根据经验,使用getProperty()
命令行属性适用于所有系统属性,而-D
仅适用于不仅在启动期间检查的属性。
答案 2 :(得分:37)
你可以添加三行
System.setProperty("java.library.path", "/path/to/libs" );
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
并导入java.lang.reflect.Field 可以解决问题