Как вы используете собственные библиотеки JNA с веб-запуском JNLP [на Mac]?

#java #jnlp #jna

#java #jnlp #jna

Вопрос:

Я пытаюсь запустить Java-приложение с помощью JNLP; приложение включает стороннюю библиотеку (Lab Streaming Layer), которая полагается на собственные библиотеки, загруженные с помощью JNA.

Насколько я понимаю, я выполнил все необходимые шаги, чтобы заставить это работать:

  1. Все собственные библиотеки находятся в файлах JAR, разделенных ОС и архитектурой.
  2. Все файлы JAR собственной библиотеки находятся на сервере и доступны по URL-адресу базы кода.
  3. Файл JNLP содержит <resources> элемент с os и arch указан с <nativelib> элементом внутри него с правильным href атрибутом.
  4. Файл JNLP не искажен и запускается нормально.

Когда я захожу, чтобы запустить свое приложение, я получаю java.lang.UnsatisifiedLinkError сообщение «Невозможно загрузить библиотеку ‘liblsl32.dylib’: не удается получить входной поток для darwin / liblsl32.dylib». Это происходит после запуска программы, при первой попытке использовать библиотеку с зависимостью от собственной библиотеки. Я исправил эту точную ошибку с помощью этой библиотеки с помощью отдельного приложения без веб-запуска, поместив dylib в правильное место. Я также попытался переименовать все библиотеки dylibs в jnilibs в соответствии с этой информацией: http://permalink.gmane.org/gmane.comp.java.jna.user/3328 , но все происходит одинаково.

Похоже, я должен иметь возможность указывать jna.library.path в файле JNLP, но я понятия не имею, что это будет, изменится ли это от запуска к запуску или как я узнаю, каким он должен быть.

Ответ №1:

Native.getWebStartLibraryPath(name) должно дать вам то, что вам нужно, чтобы помочь JNA найти собственную библиотеку.

Вы можете либо создать абсолютный путь, либо просто передать путь NativeLibrary.addSearchPath(libName, path) .

ОТРЕДАКТИРОВАНО

Вам также нужно будет назвать вашу общую библиотеку OS X с суффиксом, чтобы web start распознал ее как собственную библиотеку. .jnilib Это проблема именования, характерная для OS X.

Комментарии:

1. В настоящее время Native.getWebStartLibraryPath(имя) возвращает значение null. Проблема в том, что, хотя я знаю, как ее установить, я не знаю, на что ее установить.

2. Я забыл о проблеме с суффиксом разделяемой библиотеки OSX с JNLP.

Ответ №2:

Отредактируйте совет по использованию libo, чтобы получить единую библиотеку для поддержки нескольких архитектур (32 и 64 бит) одновременно, но основная проблема связана с 1.6, пока я разрабатываю и использую 1.8.

Основная проблема на самом деле заключается в том, что OSX использует расширение .jnilib для библиотек, которые он загружает, а не .dylib . Это означает, что если вы создаете собственный jar, вы должны убедиться, что расширение для библиотеки, которую вы хотите загрузить .jnilib , а не .dylib . Как только вы создадите банку ресурсов, содержащую это .jnilib , она будет найдена загрузчиком классов JNLP; в противном случае JNA использует некоторую эвристику, чтобы найти его.

Итак, при создании вашего jar, содержащего библиотеку, вы должны убедиться, что она имеет .jnilib расширение и находится в корне .jar , поэтому, например, если мы имеем дело с liblsl32.dylib , мы бы сделали что-то похожее на:

 ln -fs liblsl32.dylib liblsl32.jnilib
jar cf lsl32.jar liblsl32.jnilib
  

Это lsl32.jar ресурс, на который мы будем ссылаться в нашем .jnlp файле. Нам нужно подписать его; поэтому я делаю это с помощью хранилища keystore ключей с паролем password , использующим myself идентификатор.

 jarsigner -storepass password -keystore keystore lsl32.jar myself
  

Для ресурсов мне пришлось поместить ссылку в раздел ресурсов jnlp файла для Mac :

 <resources os="Mac">
  <nativelib href="darwin.jar"/>
  <nativelib href="lsl32.jar"/>
</resources>
  

Ссылки на darwin.jar необходимы для загрузки основной библиотеки JNA и lsl32.jar необходимы для загрузки liblsl32.jnilib библиотеки.

Экземпляр, ссылающийся на библиотеку с помощью:

 Native.loadLibrary("lsl32", MyClass.class);
  

он должен быть успешно загружен.

При подписании файлов .jar я убедился, что все они имеют соответствующие атрибуты Codebase / Permissions на борту, в файле с именем file.manifest . Этот файл содержит:

 Permissions: all-permissions
Codebase: http://localhost/demo
  

… убедитесь, что кодовая база соответствует вашей собственной кодовой базе, и обновите jar с помощью:

 jar cfm lsl32.jar file.manifest
  

В целях отладки, если вы используете lsof процесс java, в котором выполняется jnlp, вы можете определить, использует ли он загруженную библиотеку JNLP или загруженную библиотеку JNA, по наличию файла в списке загруженных файлов, если он использует JNLP механизм s, тогда будут ссылки нав liblsl32.jnilib списке элементов, если он использует JNA механизм s, тогда не будет упоминания о файле, поскольку он извлекается во временный файл.


В случае виртуальной машины 1.6, если ваша архитектура несовместима с виртуальной машиной, и вы загружаетесь через механизм загрузки JNA, вы получите сообщение об ошибке:

 no matching architecture in universal wrapper
  

среди шума.

Если вы используете несколько режимов (32-битный / 64-битный), вы можете объединить обе 32-битные и 64-битные библиотеки в одну библиотеку и ссылаться на нее, или вы можете просто установить 64-битную библиотеку.

Чтобы объединить их вместе, вы должны сделать что-то вроде:

 lipo -create liblsl.jnilib liblsl32.dylib liblsl64.dylib
  

тогда ссылайтесь liblsl , а не liblsl32 .

Я предпочитаю использовать более новую виртуальную машину, даже со всеми проблемами безопасности. gatekeeper не позволяет мне загружать самозаверяющие приложения на виртуальной машине 1.6, не отключая ее, что создает нестабильную среду тестирования.

Единственные проблемы с веб-запуском, которые у меня когда-либо были с JNA, были вызваны повышенной безопасностью новых версий JRE.

Комментарии:

1. Я посмотрю, поможет ли это. Я экспериментировал: если я все делаю правильно, я получаю ошибку не удается получить входной поток; если я делаю что-то неправильно (измените расширение на .jnilib, но оставьте ссылку на . dylib), я получаю собственную библиотеку, не найденную в ошибке ресурса. Я бы предположил, что встроенная библиотека повреждена, но я могу просто отлично загрузить ее при запуске Eclipse. Начинаю задаваться вопросом, является ли это проблемой с разрешениями?

2. Я также могу использовать те же библиотеки на стороне сервера в своем веб-приложении.

3. У меня также есть 32-разрядная и 64-разрядная версии библиотеки; он пытается загрузить правильную.

4. версия jre, когда вы работаете?

5. После большой работы, чтобы перестать иметь дело с последней версией «security», я использую 1.6.0_65.

Ответ №3:

Я не могу назвать это ответом, но я, наконец, заставил это работать с помощью грубой силы. Я изменил библиотеку, которую я использую, чтобы запросить .jnilib (вместо его исходного .dylib), затем создал собственную библиотеку под названием darwin.jar который содержит следующую структуру:

 /META-INF/MANIFEST.MF
/META-INF/INTERAC.DSA
/META-INF/INTERAC.SF
/liblsl32.jnilib
/liblsl32.dylib    
/liblsl64.jnilib
/liblsl64.dylib
/darwin/liblsl32.jnilib
/darwin/liblsl32.dylib
/darwin/liblsl64.jnilib
/darwin/liblsl64.dylib
  

Неясно, что в этом работает, но, по-видимому, эта комбинация содержит некоторую перестановку вещей, которые я иначе не пробовал. У меня нет времени или энергии для дальнейшего устранения неполадок и поиска точного ответа. Я подозреваю, что .версии файлов dylib не нужны, поскольку я явно изменил код для поиска .jnilib, но они есть там для полноты картины.