You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@karaf.apache.org by Philomatic <ma...@gottschaemmer.net> on 2015/02/03 12:07:19 UTC

Re: Native library and System.load

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.

Re: Native library and System.load

Posted by Achim Nierbeck <bc...@googlemail.com>.
Hi,

it's been a while I used this the last time.
Dll is just a synonym for any linked library :-)

Back to your questions, well as I pointed out, since libraries in general
can't be unloaded unless you destroy the classloader which is taken care by
the OSGi framework and only happens if there are no references to it
anymore.
That's why the library will be "renamed" inside your bundle. So to get a
hold of your library I can't remember right now, if
a) you need to load the library by the new name
b) still can do a loadLibrary as before.

That's the part you need to experiment.
But I'm certain the library will have some renaming to it, though I'm not
sure if there is some "magic symlink" to the library so a loadLibrary(name)
actually works ...

regards, Achim


2015-02-03 14:11 GMT+01:00 Philomatic <ma...@gottschaemmer.net>:

> Hi Achim,
>
> thanks for pointing out the issue with dynamic linked libraries, indeed I
> did not pay attention to the magic word "dynamic" in the blog post. My
> problem is currently that I'm not really into this topic, but have to deal
> with it from the Java side. Therefore, two questions:
>
> 1.
>
> We have only a single native library, so no reference problems between
> dynamic libs, like you've mentioned. In fact, we actually don't use .dll,
> but .so on linux arm, but that should be the same for loading in OSGi.
>
>
> > Therefore create a statically linked A.dll
>
> How can this be done? I thought a .dll is always dynamic linked?
>
> 2.
>
>
> > 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.
>
> Like said, there is no second native library which could be renamed.
> What do you mean by the "Dynamic" name?
>
> Best regards
> Patrick
>
>
>
>
>
> --
> View this message in context:
> http://karaf.922171.n3.nabble.com/Native-library-and-System-load-tp4032562p4038253.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

Re: Native library and System.load

Posted by Philomatic <ma...@gottschaemmer.net>.
Hi Achim,

thanks for pointing out the issue with dynamic linked libraries, indeed I
did not pay attention to the magic word "dynamic" in the blog post. My
problem is currently that I'm not really into this topic, but have to deal
with it from the Java side. Therefore, two questions:

1. 

We have only a single native library, so no reference problems between
dynamic libs, like you've mentioned. In fact, we actually don't use .dll,
but .so on linux arm, but that should be the same for loading in OSGi.


> Therefore create a statically linked A.dll

How can this be done? I thought a .dll is always dynamic linked?

2.


> 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. 

Like said, there is no second native library which could be renamed.
What do you mean by the "Dynamic" name?

Best regards
Patrick





--
View this message in context: http://karaf.922171.n3.nabble.com/Native-library-and-System-load-tp4032562p4038253.html
Sent from the Karaf - User mailing list archive at Nabble.com.

Re: Native library and System.load

Posted by Achim Nierbeck <bc...@googlemail.com>.
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 <ma...@gottschaemmer.net>:

> 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