Как повлиять на путь поиска System.loadLibrary () через код Java? - PullRequest
15 голосов
/ 16 февраля 2011

В проекте Java я использую стороннюю библиотеку, которая загружает некоторую нативную библиотеку через

System.loadLibrary("libName");

. Я бы хотел иметь возможность влиять на путь поиска этого метода из моего приложения., так что пользователю не нужно указывать правильное значение java.library.path в командной строке (это значение зависит от текущей ОС и архитектуры).Например, в Windows я хочу установить "lib / native / windows", в Linux 32bit - "lib / native / linux32" и т. Д.

Я пытался

System.setProperty("java.library.path", ...)

, но этоигнорируется, по-видимому, потому что JVM читает это свойство только один раз перед запуском моего кода.

Я также пытался загрузить собственный библиотека перед использованием библиотеки Java, которая зависит от него с помощью

System.load("fullPath/lib")

Этот вызов завершается успешно, но все еще будет UnsatisfiedLinkError, когда собственная библиотека снова загружается с помощью System.loadLibrary ().

Единственный найденный мной способ - это следующее:

  • Добавитьинтерфейсы, которые абстрагируют весь API внешней библиотеки.
  • Используйте только эти интерфейсы в остальной части кода.
  • Добавьте классы, которые реализуют интерфейсы, и делегируйте библиотеке.
  • Напишите собственный ClassLoader, который
    • перезаписывает findLibary () так, чтобы собственная библиотека находилась по правильному пути
    • перезаписывает loadClass () и загружает все классы внешней библиотекии слой-обертка сам по себе вместо попытки делегировать его родителю, как если бы ClassLoader по умолчанию делал бы
  • Убедитесь, что интерфейсы загружены с обычным ClassLoader и классами обертывания и внешней библиотекойзагружаются с моим собственным ClassLoader.

Это работает, но я нахожу это очень сложным и требует больших усилий, потому что мне нужно добавить все эти интерфейсы.Есть ли более простой способ?

Ответы [ 5 ]

5 голосов
/ 17 июня 2014

Мне нужно было изменить путь DLL для моих модульных тестов.Я попробовал следующий хак, и он сработал:

System.setProperty( "java.library.path", "/path/to/libs" ); 
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );

Для объяснения см. оригинальную ссылку .

1 голос
/ 16 февраля 2011
  1. Вы не можете изменить путь к библиотеке для работающей JVM.
  2. Вы не можете загрузить собственную библиотеку более одного раза ... и вы не можете выгрузить собственную библиотеку, чтобы вы могли загрузить ее снова: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4171986

Основываясь на ваших комментариях выше (в частности, на поведении сторонней библиотеки), я бы сказал, что ваш лучший вариант - правильно указать путь к библиотеке при запуске JVM.

1 голос
/ 28 августа 2011

Я пытался загрузить нативную библиотеку Growl для приложения Java на моем Mac, где библиотека находится в корне пути к классам моего приложения:

System.load(GrowlUtils.class.getResource("/libgrowl.jnilib").getFile().toString());
0 голосов
/ 21 мая 2019

Хотя технически правильные эти ответы ошибочны. Установка переменных среды PATH в Windows или LD_LIBRARY_PATH в unix изменит место, где jvm ищет библиотеки: Что такое LD_LIBRARY_PATH и как его использовать?

в Linux: экспорт LD_LIBRARY_PATH = / usr /.../ затем: Ява ....

0 голосов
/ 16 февраля 2011

Есть ли более простой способ?

Да, предоставьте пакетные / скриптовые файлы для запуска приложения.Затем вы можете установить правильный путь в пакетном файле / файле оболочки или даже прочитать значение из переменной среды.Гораздо проще, чем пытаться сделать это изнутри приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...