В проекте Java я использую стороннюю библиотеку, которая загружает некоторую собственную библиотеку через
System.loadLibrary("libName");
Я хотел бы иметь возможность влиять на путь поиска этого метода из моего приложения, так что пользователю не нужно указывать правильное значение java.library.path в командной строке (это значение зависит от текущая ОС и архитектура). Например, в Windows я хочу установить его в "lib/native/windows", на Linux 32bit на "lib/native/linux32" и т.д.
Я пробовал
System.setProperty("java.library.path", ...)
но это игнорируется, по-видимому, потому, что JVM читает это свойство только один раз, прежде чем мой код будет запущен.
Я также попытался загрузить собственный libray перед использованием библиотеки Java, которая зависит от нее с помощью
System.load("fullPath/lib")
Этот вызов завершается успешно, но все равно будет UnsatisfiedLinkError, когда загружаемая библиотека снова загружается с помощью System.loadLibrary().
Единственный способ, которым я нашел, это следующее:
- Добавить интерфейсы, которые абстрагируют весь API внешней библиотеки.
- Используйте только эти интерфейсы в остальной части кода.
- Добавить классы, реализующие интерфейсы и делегированные в библиотеку.
- Напишите собственный ClassLoader, который
- перезаписывает findLibary(), так что собственная библиотека находится в правильном пути
- перезаписывает loadClass() и загружает все классы внешней библиотеки и слоя-оболочки самостоятельно, вместо того, чтобы пытаться делегировать ее родительскому элементу, например, класс ClassLoader по умолчанию будет выполнять
- Убедитесь, что интерфейсы загружены обычным ClassLoader, а классы-оболочки и внешняя библиотека загружаются с помощью моего собственного ClassLoader.
Это работает, но я нахожу его очень сложным и много усилий, потому что мне нужно добавить все эти интерфейсы. Есть ли более простой способ?