Friday, March 6, 2009

Maven, OSGi, and native libraries on Mac OS

I’m currently involved in a project dealing with native library. As a software engineering fan, I decide to set a project containing both unitary tests and integration test (thanks to the maven-junit4osgi-plugin, of course ☺).

However yesterday a strange issue appeared. The integration tests using the native library were executed “successfully”, but when I ran the same bundles in our application, I get UnsatisfiedLinkError. For all of you that already meet this Exception, it is always a bad thing.

What really does it means? No native libraries match with the actual architecture/os/… or if one matches it cannot be loaded for an obscured reason.

Hum, but I ran junit4osgi and the regular application on the same machine, my Mac book pro with Mac OS X! So, why junit4osgi was able to load the library and not a normal Felix platform (using exactly the same bundles)?

It takes at least 3 hours of debugging to understand what happened. First, I claimed against Maven ☺ (as everyday!), but in fact Maven was not guilty (just a little bit, because it is Maven). I also tried the application on Felix and Equinox. Despite Equinox was a little more verbose on the issue, the library was not loaded. I try different version of Felix, and always the same error: UnsatisfiedLinkError ! The worst thing happened when one of my co-worker executed the application on Windows correctly!

WTF????

Junit4OSGi test reports contain the system properties, and so I decided to compare the properties between junit4osgi and the normal runtime. And here arrived the light: maven and the runtime does not use the same JVM.

The OS provides the ‘mvn’ executable.
Clement-Escoffier:integration-test clement$ which mvn
/Users/clement/dev/apache-maven-2.0.9/bin/mvn

This executable uses Java 5 (the default JVM on Mac). So when running maven-junit4osgi-plugin, it uses this 32bits VM. In this context, the native library was loaded correctly.

However, when I ran the application, I use a Java 6 VM (64bits architecture). In this case, the library cannot be loaded. Despite it match the native library clause of my bundle; the library was not compiled to run on a 64bits CPU.

So finally, three hours spend for just a JAVA_HOME issue…

7 comments:

Anonymous said...

Hi Clement,

I have a similar problem and I was wondering if you could help me with it.

I am using Eclipse on Windows XP, here I use it to compile my classes and then I exported the bundles in order to install them using Equinox in console mode on UBUNTU.

The problem is the nex one:
-If I use LIRC packages in easy Java application without using Equinox, I do not get any error at all.

But If I use Equinox in console mode, when I tried to start the bundle which use LIRC packages, I got java.lang.UnsatisfiedLinkError: Can’t load library: /org/lirc/socket/libjunixsocket.so.

For this reason I think It could be a problem similar the your, because I think maybe Equinox.jar framework is using a JVM version different the UBUNTU one, could you tell me how could I solve this?

Thank you in advance

David

Clement said...

Hi,

In my case, it was always run inside OSGi. In your case it seems that is not the case.
The first attempt is outside the OSGi container, so it is the "regular" JNI mechanism.
In the second attempt, you're inside OSGi. Did you correctly wrote the native library header in your bundle manifest? Could you post it?

Anonymous said...

Hi,

I have tried a lot of changes, at the beggining I achieved to load in the same bundle the library libjunix.so in my bundle but next times, when I tried to load native library in other bundle I get next error when I tried to export from Eclipse:

Error
Reason:
Problems during export
Details:
Unable to find plug-in: MyPluginName_1.0.0.

It is very strange becuase the only thing that I do it is create a new bundle from a jar where are the packages what I want to use together the native library.

My header is the next one:

Bundle-NativeCode: libjunixsocket.so ;
processor = i386 ; osname = Linux


I do not why I can not export this, I have tried in Ubuntu running Eclipse in Ubuntu, and I do not have this problem, but I continue having the same mistake:

java.lang.UnsatisfiedLinkError: Can’t load library: /org/lirc/socket/libjunixsocket.so.

Any idea?

Thank you in advance

Clement said...

Hum,

You should either provide the native library for Windows or set it as optional:
Bundle-NativeCode: libjunixsocket.so;processor=i386 ;osname=Linux,*

Clement

Anonymous said...

Hi,

Thank you for your answer.

That was my problem, as I just run it in Linux, I did not know that it was neccesary to provide for other operative systems.

Now that this problem is solved I am getting the next Exception:

java.lang.ExceptionInInitializerError instead of UnsatisfiedLinkError so I suppose that OSGI is loading well the native library, although it continues being odd because as I told you, if I launch a easy application using LIRC classes without OSGI, just typing java myLircApplication.class everything works fine, but If I do the same but as a bundle in OSGI I get the last Exception.

Any idea?

Thank you in advance

Anonymous said...

Hi again,

I am looking through the code in the LIRC packages and I am finding a lot of references to the java method System.getProterties("Property_NAME"), do you know if OSGI take the same system properties as JVM or I have to type explicitly as part of my command when I launch OSGI framework in console mode.

When I launch Lirc application without OSGI, it works fine, so maybe it is because of JVM are different in Equinox and JVM in Linux, how could I do that both use the same JVM in order both of them have the same environments and system properties?

This is just an idea, since I do not really know why my code in OSGI is not working and it is working without OSGI.

Thank you for your time

David

Clement said...

Hi,

Did you try to launch a "regular" app using this library with the same JVM as the one that you use to launch Equinox?

I don't know LIRC so my help is quite limited... :-(

Clement