Свойство это устанавливается один раз, перед запуском JVM, через глобальные system properties, или как ключ -Dname=value для JVM, и после этого оно становится read-only. Точнее, менять-то его можно, но никакого эффекта на работу программы это не окажет, т.к. после того как вы обновите это свойство, JVM не перечитает его и не будет использовать новое значение.
Однако, возможность менять java.library.path на лету была бы очень кстати - тогда бы не пришлись много раз генерить, переписывать и перезаписывать скрипты для запуска JBoss-a, например, чтобы отразить в них все нужные пути ДО старта аппсервера.
И такая возможность, изменять эти пути, по которым JVM ищет нативные библиотеки, на самом деле есть. Подробно это объяснено тут:
http://blog.cedarsoft.com/2010/11/setting-java-library-path-programmatically/
и еще вот тут:
http://nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime/
А здесь я опишу сам механизм загрузки, и почему то, что описано по ссылкам, работает. Обычно, нативные библиотеки загружаются следующим через статический инициализатор:
static {
try {
System.loadLibrary("dp-integ"); } }
Этот вызов внутри выглядит так:
public static void loadLibrary(String libname) { Runtime.getRuntime().loadLibrary0(getCallerClass(), libname); }И далее
synchronized void loadLibrary0(Class fromClass, String libname) { // Проверяем, разрешено ли загружать данную конкретную библиотеку SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkLink(libname); } if (libname.indexOf((int)File.separatorChar) != -1) { throw new UnsatisfiedLinkError("Directory separator" + "should not appear in library name: " + libname); } ClassLoader.loadLibrary(fromClass, libname, false); }
Т.е. в итоге, нативные библиотеки загружаются, так же как и обычные классы, через ClassLoader. У класса ClassLoader есть два свойства, в которых кешируются проинициализированные пути поиска.
// The paths searched for libraries static private String usr_paths[]; static private String sys_paths[];
Код метода ClassLoader.loadLibrary(fromClass, libname, false), довольно длинный, и загроможденный многочисленными проверками, в сокращенном виде выглядит это так.
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,
boolean isAbsolute) {
ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader();
if (sys_paths == null) {
// это то, что нам нужно
usr_paths = initializePath("java.library.path");
// а это для тех библиотек, которые загружаются из классов,
// загруженных из boot classpath.
sys_paths = initializePath("sun.boot.library.path");
}
// Дальше попытка загрузить библиотеку, и дальше,
// если найти ее так и не удалось, то -
// Oops, it failed
throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
}
Таким образом, теперь механизм загрузки нативной библиотеки стал более понятен.
Вы можете либо выставить в null свойство sys_paths у класслоадера, либо просто поменять его, добавив к нему нужный путь к вашим нативным библиотекам.
Комментариев нет:
Отправить комментарий