Загрузите DLL (используя JNA) внутри пакета OSGi.

StackOverflow https://stackoverflow.com/questions/1375550

  •  21-09-2019
  •  | 
  •  

Вопрос

OSGi не может найти мой файл DLL, и я не могу понять, почему.

В настоящее время у меня есть файл DLL (foo.dll) в корне моего пакета, я также пробовал разместить его в libs каталог.

Манифест рассматриваемого пакета выглядит примерно так:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: foobundle
Bundle-SymbolicName: com.foo.bar
Bundle-Version: 1.0.0
Bundle-Vendor: me
Import-Package: com.sun.jna,
 com.sun.jna.ptr,
 com.sun.jna.win32
Export-Package: com.foo.bar
Bundle-NativeCode: foo.dll;
 osname=WindowsXP;
 processor=x86

Затем в моем интерфейсе JNA я выполняю loadLibrary (согласно документации):

public interface MyFooInterface extends com.sun.jna.Library{
    static final MyFooInterface INSTANCE = (MyFooInterface)com.sun.jna.Native.loadLibrary("foo", MyFooInterface .class);

    // specific interface defs here...
}

Затем в другом классе я пытаюсь использовать интерфейс JNA.

// ...code
int var = MyFooInterface.INSTANCE.bar();
// ...more code

У меня есть JNA через другой пакет (который экспортирует com.sun.jna и другие пакеты, импортированные выше), но я также попытался упаковать его с помощью пакета, определенного здесь (и в этом случае добавил его в путь к классам и т. д.).

Я также попытался указать Bundle-NativeCode: /foo.dll.

Также интересно отметить соответствующие свойства OSGi (которые я извлек с помощью getprop)

org.osgi.framework.os.name=WindowsXP
org.osgi.framework.processor=x86

Даже после всего этого (и при каждом испытании, которое я проводил) я всегда получаю следующую ошибку (и трассировка стека не отображается):

java.lang.UnsatisfiedLinkError: Unable to load library 'foo': The specified module could not be found.

...так чего мне не хватает?

Редактировать:Я также должен отметить, что я успешно протестировал код интерфейса JNA и библиотеку DLL, с которой он взаимодействует, в рамках программы тестирования JUnit.

Редактировать 2:Добавление этого кода в класс, вызывающий библиотеку, похоже, позволяет JNA найти библиотеку (когда Native.loadLibrary позвонят позже).Кажется, я смогу избежать этого вызова на основе директивы Bundle-NativeCode в манифесте.Очевидно, что после загрузки библиотеки Native.loadLibrary захватывает существующий ее экземпляр, но я бы предпочел не зависеть от этой тактики, специфичной для порядка.

static{
    System.loadLibrary("foo");
}
Это было полезно?

Решение

Проблема заключается в специализированном вызове JNA loadLibrary, который не поддерживает OSGi.Когда вы вызываете loadLibrary из пакета OSGi, он будет использовать загрузчик классов OSGi (который поддерживает пакет), чтобы найти, где находится DLL, и в этом случае извлечь ее из пакета и сделать ее загружаемой через System.loadLibrary(). вызов против определенного места.

Поскольку этот JNA, похоже, (а) не поддерживает OSGi и (б) излишен, почему бы вместо этого просто не использовать System.loadLibrary()?

Если вам нужно написать оба, выполните System.loadLibrary() в методе start() пакета в BundleActivator, что приведет к включению собственной библиотеки (вероятно, вы захотите убедиться, что если ее невозможно загрузить, пакет ни в коем случае нельзя запускать).

Другие советы

Глядя на документацию JNA, там говорится:

  • Сделайте целевую библиотеку доступной для вашей программы Java.Есть два способа сделать это:
    • Предпочтительным методом является установка jna.library.path системное свойство на путь к вашей целевой библиотеке.Это свойство похоже на java.library.path но применяется только к библиотекам, загружаемым JNA.
    • Перед запуском виртуальной машины измените соответствующую переменную среды доступа к библиотеке.Это PATH в Windows, LD_LIBRARY_PATH в Linux и DYLD_LIBRARY_PATH на OSX.

Итак, чтобы обойти этот недостаток, вы можете определить абсолютный путь к библиотеке и загрузить его.

Предполагая, что это стандартный загрузчик классов Eclipse, вы можете сделать ClassLoader.findLibrary() который должен найти локальную библиотеку в комплекте.

Я предлагаю вам попробовать упаковать dll в виде jar:

jar cvf foo.dll.jar foo.dll

и загрузите банку как обычную библиотеку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top