2011-03-24 82 views
40

我加载了放置在./lib中的外部库。这两个解决方案是否设置java.library.path等效?在控制台是-Djava.library.path = ...相当于System.setProperty(“java.library.path”,...)

  1. 设置路径执行时,罐子:在代码

    java -Djava.library.path=./lib -jar myApplication.jar 
    
  2. 设置路径加载库之前:

    System.setProperty("java.library.path", "./lib"); 
    

如果他们是等价,为什么在第二个解决方案中,Java可以找不到库,而第一个可以吗?

如果不是,有没有办法在代码中设置路径?

+0

'java.library.path'指*目录*不是*文件* – jacktrades 2015-04-02 18:15:46

回答

44

一般而言,两种方法的净效应都相同,系统属性java.library.path设置为值./lib

但是,某些系统属性仅在特定时间点进行评估,例如JVM的启动。 如果java.library.path属于这些属性之一(并且您的实验似乎表明了这一点),那么使用第二种方法除了在将来的调用getProperty()上返回新值之外没有明显效果。

作为一条经验法则,使用-D命令行属性适用于所有系统属性,而System.setProperty()仅适用于不仅在启动过程中进行检查的属性。

43

尽管没有很好的文档记录,但就System.loadLibrary()方法而言,java.library.path系统属性是“只读”属性。这是一个reported bug,但它被Sun关闭,而不是被修复。问题在于JVM的ClassLoader在启动时读取一次该属性,然后将其缓存起来,不允许我们在之后以编程方式更改它。除System.getProperty()方法调用外,行System.setProperty("java.library.path", anyVal);将不起作用。

幸运的是,有人posted a workaround on the Sun forums。不幸的是,该链接不再有效,但我确实发现了the code on another source。这里是你可以用它来解决不能够设置java.library.path系统属性的代码:这可能不是在所有的平台和/或JVM中工作:

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"); 
    } 
} 

警告。

+3

看看[这个较新的答案](http://stackoverflow.com/a/24988095/346561)@luyifan似乎完成与这个答案相同的东西,代码少。 – 2015-08-24 16:34:42

32

您可以添加三行

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中 这是确定要解决的问题

+2

这个效果很好(比起Jesse Webb的解决方案,我们自己建造的温度路径要简单) – 2014-08-13 13:31:02

+0

这是一个救生员。 Sun/Oracle似乎懒惰不提供从特定的,运行时定义的目录加载库的更直接方式。 – gromit190 2017-05-05 08:44:40