Ответ 1
Из исследования, которое я делал в прошлом, есть только два способа загрузки загруженных загружаемых библиотек: изменение java.library.path
и использование System.loadLibrary
(я чувствую, как это делают большинство людей) или используя System.load
с абсолютный путь.
Как вы уже упоминали, возиться с java.library.path
может раздражать с точки зрения настройки SBT и Eclipse, и я не думаю, что это можно сделать автоматически для исполняемого банку.
Итак, это оставляет System.load
. Что касается написания собственных собственных библиотек, то вы можете сделать следующее:
- Создайте задачу SBT, которая компилирует ваши собственные источники (с
javah
иgcc
), берет полученные .so файлы и любые файлы .so, от которых она зависит, помещает их в банку (как ресурсы) в целевой и добавляет путь к банке вunmanagedJars in Compile
. - Создайте метод Scala для загрузки библиотеки. Вместо вызова
System.loadLibrary
он будет использоватьClass.getResourceAsStream
для чтения библиотеки,File.createTempFile
, чтобы записать ее где-нибудь в файловой системе, иSystem.load
, чтобы загрузить ее в JVM. - Теперь вместо вызова
System.loadLibrary
, как и раньше, вызовитеMyClasspathJniLoader.loadLibrary
.
Это будет работать с SBT run, Eclipse и исполняемыми банками без дополнительной настройки (хотя я не знаю, как proguard знает, какие ресурсы включать).
Теперь, когда уже записаны собственные библиотеки сторонних разработчиков, некоторые из них, такие как jblas, уже используют этот подход с "жирной флягой". Если они ожидают, что вы настроите java.library.path
, а затем они вызовут System.loadLibrary
, когда они захотят, вам нужно будет сделать магию, чтобы сделать эту работу.
Я не пробовал это, но это решение может работать:
- Используйте аналогичную задачу SBT, чтобы поместить все библиотеки на свой собственный путь в банку в качестве ресурсов и поместить эту банку в clsaspath.
- Создайте метод Scala, который принимает функцию и список имен библиотек, создает каталог temp, читает эти библиотеки из ресурсов jar в файлы в каталоге temp, добавляет каталог temp в
java.library.path
, вызывает передается в функции и, наконец, возвращаетjava.library.path
назад к тому, что было раньше. - При первом вызове в родную библиотеку (когда она, по-видимому, будет статически инициализироваться и вызовет
System.loadLibrary
), оберните этот конкретный вызов в свой метод со списком библиотек, которые он будет загружать. Таким образом, когда он вызываетSystem.loadLibrary
, все его библиотеки будут наjava.library.path
и будут загружены успешно.
Очевидно, это раздражает, поскольку перед его использованием необходимо вручную инициализировать библиотеку сторонних разработчиков, но представляется более целесообразным обернуть все точки инициализации (ваши основные функции и инициализации теста), чем это сделать, чтобы получить все ваши инструменты для правильной установки java.library.path
. И это может быть даже проще, если вы уже имеете свой собственный слой абстракции над третьей стороной, поэтому на самом деле вам нужно только один пункт инициализации.
Если это похоже на реалистичное решение, я могу добавить дополнительные сведения о задаче SBT или методах оболочки Scala, если вы запутались.