Thanks to grgrzybek, this project is based on:
https://github.com/grgrzybek/f2f2019/
This project demonstrates usage of JNI with Karaf. The use case is:
- Karaf (Java) bundle is installed
- Karaf bundle calls Native C Code
- Native C Code calls back into the Karaf bundle
The following versions were used during development/testing:
- Red Hat Fuse 7.6.0 (Karaf/OSGi container)
- Openjdk 1.8
- Fedora 32
From the 'c' project, execute:
$ mkdir build
$ cd build/
$ cmake ../
$ cmake --build .
Typically, the Java project can simply call System.load with the shared library location. In the Karaf/OSGi environment, the following will happen if the OSGi bundle is uninstalled/installed:
The activate method has thrown an exception
java.lang.UnsatisfiedLinkError: Native Library /opt/native-bridge/libnbridge.so already loaded in another classloader
To avoid this, the native library is included in the bundle itself, and the bundle's headers are modified accordingly.
Copy the share library to the Java project so it's available during the next step (build/install Java Project):
$ cp c/build/libnbridge.so java/src/main/resources/
See the pom.xml for the bundle headers, which make it easier to load the library from the bundle:
<Bundle-NativeCode>libnbridge.so;osname=linux;processor=x86-64</Bundle-NativeCode>
From the Java project, execute:
$ mvn clean install
karaf@root()> osgi:install -s mvn:com.rh.example/karaf-jni/1.0.0
Observe the following logs from stdout and the logs:
C code writes the following to stdout
native code received: hello from karaf
Java code, in the callback, writes the following to the logs:
INFO [pipe-bundle:install $args] native code says hello
If the JNI bridge class changes and a new C header is needed, re-generate the header from the base project directory:
$ javah -cp java/target/classes/ -d c/include/ com.rh.example.NativeBridge