Hi,
(replying on this one, as it adresses exactly my problem.)
We're also stuck with loading native libraries in an OSGi App in Karaf with
Equinox as framework.
Maybe I'm a little bit blindfolded, so far I've got the following:
Our native lib is inside our bundle jar.
We have declared it in our Manifest Header with:
Bundle-NativeCode: lib/win_x86/RS485.dll;
processor=x86;
osname=win32,
lib/linux_arm/libRS485.so;
processor=arm;
osname=linux,
...
(We do not have this in our pom.xml, as our MANIFEST.MFs aren't
auto-generated by maven. However, I'm wondering what the (side-)effects
would be? )
And in the Activator class:
@Override
public void start(BundleContext context) throws Exception {
Activator.context = context;
if (OSDetector.getOperatingSystemType().equals(OSType.Linux)) {
System.loadLibrary("RS485");
logger.info("RS485 native library loaded");
RS485.setSimulation(false);
} else {
RS485.setSimulation(true);
}
(Are there any benefits by putting this into a static block instead of the
Activator.start method?
Plugin is a Singleton, ofc.)
This works as a one-time solution:
If I install and start the bundle in a clean Karaf installation, everything
gets loaded and is working peachy.
However, if I try to stop the bundle, uninstall it and install a new
version, I'll get a Java LinkageError.
Even after a Karaf restart, there's still the LinkageError and the bundle
can't be loaded.
(Note: If I update the bundle directly and restart karaf, this does not
occur always! Will check further into this behavior.)
So far, I understand this by the OSGi Spec and jbonofre's answer:
jbonofre wrote
> Which is normal, as the uninstall of a bundle doesn't unload the native
> library.
>
> That's why, it would be better to put the dll/so in Karaf lib.
However, I don't want to put the lib in karaf/lib folder, for two reasons:
1. I'd have to load it via System.loadlibrary(...) anyways, right? Which
would lead me to the same behavior, as the lib does not get unloaded by a
bundle stop?
2. I could not update the lib by updating our bundle. This is actually our
goal, as the lib is a needed self development in C.
What I don't understand is the "use the bundle loader to load native libs"
thing, mentioning this piece of code by Achim and JB:
> static {
> try {
> System.loadLibrary("crypt"); // used for tests. This library in
> classpath only
> } catch (UnsatisfiedLinkError e) {
> try {
> NativeUtils.loadLibraryFromJar("/natives/crypt.dll"); //
> during runtime. .DLL within .JAR
> } catch (IOException e1) {
> throw new RuntimeException(e1);
> }
> }
> }
the try block works for us during runtime with limits, like mentioned above.
But where does
NativeUtils.loadLibraryFromJar("/natives/crypt.dll");
come from? If you're referencing this
<http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar/>
blogpost, I wonder:
Why is this working? Where's the difference between loading with
System.loadLibrary(...) and copying the file to a tempdir and loading via
System.load(PathToTempFile)? Besides, Adan Heinrich states:
> This approach is just fine if you have dynamic library outside the
> application’s JAR archive, but when bundling dynamic library within the
> JAR it is necessary to extract the library into filesystem before loading
> it. And that’s exactly what my code does.
However, loading directly from within the jar is at least possible in OSGi?
No need for extracting to file system and wirking with absolute paths.
tl;dr
How can I (re-)load successfully our native lib during runtime with update
possibility?
Best regards
--
View this message in context:
http://karaf.922171.n3.nabble.com/Native-library-and-System-load-tp4032562p4038250.html
Sent from the Karaf - User mailing list archive at Nabble.com.