Hi, the main issue is with dynamically loaded native libraries. For example you have two dll's in your Bundle X, A.dll and B.dll where A references B, this only works once. With an update the dlls are supposed to be renamed to A2.dll and B2.dll where the linkage of A to B doesn't work anymore. Therefore create a statically linked A.dll
This doesn't matter for references to dlls outside the classloader scope, dlls that reside in the system path. For example if B.dll referencs X.dll which is in the system path it will work. To update bundles that contain native parts, make sure you have a static linked librarie, this way it's updatable by osgi and just use loadLibrary(name) the name might need to be "Dynamic" as the container might rename the dll because a dll can't be unloaded unless the corresponding class-loader is destroyed. During this time the second native library will be renamed. regards, Achim 2015-02-03 12:07 GMT+01:00 Philomatic <[email protected]>: > 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. > -- Apache Member Apache Karaf <http://karaf.apache.org/> Committer & PMC OPS4J Pax Web <http://wiki.ops4j.org/display/paxweb/Pax+Web/> Committer & Project Lead blog <http://notizblog.nierbeck.de/> Co-Author of Apache Karaf Cookbook <http://bit.ly/1ps9rkS> Software Architect / Project Manager / Scrum Master
