Is -Djava.library.path =... эквивалентно System.setProperty( "java.library.path",...)
Загружаю внешнюю библиотеку, помещенную в ./lib
. Эти два решения задают эквивалент java.library.path?
-
Задайте путь в консоли при выполнении jar:
java -Djava.library.path=./lib -jar myApplication.jar
-
Задайте путь в коде перед загрузкой библиотеки:
System.setProperty("java.library.path", "./lib");
Если они эквивалентны, почему во втором решении Java не может найти библиотеку, в то время как первая в порядке?
Если нет, существует ли способ установить путь в коде?
Ответы
Ответ 1
Вообще говоря, оба подхода имеют одинаковый сетевой эффект в том, что системное свойство java.library.path
установлено в значение ./lib
.
Однако некоторые системные свойства оцениваются только в определенные моменты времени, такие как запуск JVM. Если java.library.path
входит в число этих свойств (и ваш эксперимент, похоже, указывает на это), то использование второго подхода не будет иметь заметного эффекта, кроме как вернуть новое значение при будущих вызовах getProperty()
.
Как правило, использование свойства командной строки -D
работает во всех свойствах системы, а System.setProperty()
работает только с свойствами, которые не только проверяются во время запуска.
Ответ 2
Несмотря на то, что он недостаточно хорошо документирован, системное свойство java.library.path
является свойством "только для чтения" в отношении метода System.loadLibrary()
. Это сообщенная ошибка, но она была закрыта Sun, а не исправлена. Проблема в том, что JVM ClassLoader читает это свойство один раз при запуске, а затем кэширует его, не позволяя нам впоследствии его программно изменять. Строка System.setProperty("java.library.path", anyVal);
не будет иметь эффекта, кроме вызовов метода System.getProperty()
.
К счастью, кто-то опубликовал обходной путь на форумах Sun. К сожалению, эта ссылка больше не работает, но я нашел код в другом источнике. Вот код, который вы можете использовать для работы, не имея возможности установить системное свойство 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.
Ответ 3
вы можете добавить три строки
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
Это нормально для решения проблемы