Загрузите DLL (используя JNA) внутри пакета OSGi.
Вопрос
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
и загрузите банку как обычную библиотеку.