Issue using two dynamic libraries with Java JNI interface - java

I have a JNI library "lib.so" that has a dependancy on "lib2.so". When I compiled on another platform with lib2.so as static, all was fine, but when compiling dynamically, I get an UnsatisfiedLinkError. In particular, it says "lib.so: undefined symbol: mysymbol_name". I have verified that mysymbol_name is inside of "lib2.so" using the nm tool. I am also loading "lib2.so" to Java before "lib.so".
Java Code:
System.load("/pathto/lib2.so"); // no error
System.load("/pathto/lib.so"); // triggers UnsatisfiedLinkError
C++ compile stage
g++ -c -fPIC {{{.cpp files}}} {{-I,-L directives}} --std=c++11 -Wl,-soname,lib2.so
C++ link stage
g++ {-L,-I directives} -o lib.so {{.o files}} -l:lib2.so
I am inexperienced with compiling and linking for C/C++, so I'm not sure where the error lies. The C++ compiles and links, so that would mean there is an issue with loading it into Java right?
Update: I have checked ldd lib.so and found that lib2.so is not linked.

Related

Compilation using Pi4j

I run into the following problem: Upon running of the GPIO-example for my device built-in in Pi4J, I get an JNI error, followed by a NoClassDefFoundError for the com/pi4j/io/gpio/GpioProvider.
After some searching (both here and other websites) I came to the conclusion that I was missing the pi4j-gpio-extension.jar. Turns out I have to include these specifically while compiling. I was using:
pi4j --compile Gpioblabla.java
which is a macro/shorthand/dont know for
+ javac -classpath '.:classes:*classes:/opt/pi4j/lib/*' -d . Gpioblabla.java
This successfully compiles.
After running the program I get the NoClassDefError.
So the question is, how to explicitly include certain .jar files in pi4j/javac compilation?
Found the error. You need to run it with the classpath as well. So run it like:
java -classpath '.:classes:*classes:/opt/pi4j/lib/*' Gpioblabla

JNI: Problems compiling 64-bit native libraries

I compiled a native DLL file on Windows (64-bit) with GCC flags -c and -o Name.dll.
When I did System.load("fullpahhere"), I get this error:
java.lang.UnsatisfiedLinkError: RenderControl.dll: %1 is not a valid Win32 application
If I recompile adding a blank main() method to the C source and removing the -c flag, it then fails with an UnsatisfiedLinkError that says it can't load a 32 bit DLL on a 64 bit machine.
Why is Java calling a DLL with no main method invalid? Doesn't that ruin the whole point of DLL files and the JNI?
Update
I fixed the main() issue. This GCC invocation setup works:
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I "C:\Program Files\Java\jdk1.6.0_32\include" -I "C:\Program Files\Java\jdk1.6.0_32\include\win32" -shared *.c -o lib.dll
I still need to figure out the JVM Architecture problem, however.
Where can I find a MinGW installation that is capable of compilnig 64 bit code? It seems my standard MinGW install only does 32 bit.
If I can get my hands on that, how do I decide which library to load in Java? Is there a System property that shows the JVM arch (NOT the OS arch)?
If you use the MinGW32 compiler, you cannot produce 64-bit code. This is something that is most likely intentional. Similar issues with other people I quickly looked up seem to suggest that you're trying to use a 32-bit native binary with 64-bit java.
Try compiling with mingw-w64 and see if that allays the problem.
There's also the possibility that your library simply isn't in the library path and that it's not being found even though you're giving System.load the full path, in which case you should make sure that your DLL is in the correct location for native libraries.
Check out http://tdm-gcc.tdragon.net/, to download TDM-GCC which gives an easy installation on Windows for MinGW-w64 referenced above. You can use the following code to generate a 64-bit dll after installint TDM-GCC.
"C:\MinGW64\bin\gcc.exe" -m64 -c -I"C:\Program Files\Java\jdk1.6.0_26\include" -I"C:\Program Files\Java\jdk1.6.0_26\include\win32" HelloWorld.c
It is the "-m64" which makes it 64 bit. This is run from the same directory as the HelloWorld.c C Code Source File. This generates the HelloWorld.o C Code Object File in the same directory as run..

UnsatisfiedLinkError when using JNI?

I want to call a C program from Java program using JNI in linux ubuntu.
I am new to this and I have tried the sample program given in http://www.ibm.com/developerworks/java/tutorials/j-jni/section2.html
. I have already created the .java, .h , .c and .so files. But when i tried to run the program I am getting the following error.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no Sample1 in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1738)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at Sample1.main(Sample1.java:13)
This exception is indicating that the .so is not available to the JVM.
Adding the directory where the .so exists to the LD_LIBRARY_PATH will resolve this. If the .so depends on other .so libraries the directories where these .so exist will also need added to LD_LIBRARY_PATH.
I've just tried to get the same sample to work on my CentOS and got the same error as you. As already answered, JVM failed to find the so file needed. I succeeded to get it to work by following the steps below using gcc:
$ javac Sample1.java
$ javah Sample1
$ # Include paths must also be specified using -I option in the following gcc command line!
$ gcc -shared -I...snip... Sample1.c -o libSample1.so
$ # Library path for libSample1.so must also be specified!
$ java -Djava.library.path=...path/to/libSample1.so... Sample1
If you omit the "lib" prefix of the shared library, JVM fails to find it for some reason.
I don't know why. I am not familiar with the naming convention of shared libraries in Linux.
I hope this post could help.

OpenKinect Java JNI error: libOpenKinect.so: undefined symbol: libusb_init

I get the following error when making the Java JNI Wrapper for OpenKinect:
java: symbol lookup error:
/home/richard/libfreenect/wrappers/java/dist/libOpenKinect.so:
undefined symbol: libusb_init
I use the Ubuntu Manual Install with the following exceptions:
git://github.com/michael-nischt/libfreenect.git instead of git://github.com/OpenKinect/libfreenect.gitworks, because the JNI wrapper isn't integrated into the main distribution.
freeglut3-dev instead of libglut3-dev.
I am able to run glview successfully.
I modify the build.sh script so that LIBFREENET_LIBRARY refers to the correct directory. The jar build then compiles successfully. The example file compiles correctly.
javac -d ./ -classpath .:./dist/OpenKinect.jar ./OpenKinect/src/Example.java
I get the error when I run:
java -Djava.library.path=./dist -classpath .:./dist/OpenKinect.jar Example
Has anyone else experienced this error?
Has anyone been able to resolve this error?
Verify the dependencies of the shared library libOpenKinect.so:
ldd /home/richard/libfreenect/wrappers/java/dist/libOpenKinect.so/libsample.so
You must find a line with libusb-1.0.so.0. If not this mean that the library is not link to libusb. A solution is to recompile the shared library with the flag -lusb-1.0:

Why doesn't GCJ find the classes from my imported packages?

I want to compile a small Java application to a Windows executable.
The application is very small, only a single main class, but it uses Apache POI.
When I compile it, everything works fine, as long as I put the POI Jar into the class path argument.
But when it comes to linking, GCJ cannot resolve the references the classes in the POI package. The messages are all like this:
undefined reference tp 'org::apache::poi:hssf:usermodel:HSSFWorkbook::class$'
What do I have to do in order to link my application?
You have to compile the imported Jars into .so libraries separately. Make sure to provide the Jars in the --classpath, both while compiling the libraries as while compiling your code.
An example, where I'm compiling the GNU crypto library:
gcj --classpath=source/:libs/gnu-crypto.jar -fjni -c libs/gnu-crypto.jar -o libs/gnu-crypto.o
gcj -shared -fPIC -o libs/libgnu-crypto.o libs/gnu-crypto.o -o libs/libgnu-crypto.so
Finally, execute your executable through a shell script referencing the library path. For example:
#!/bin/sh
export LD_LIBRARY_PATH=./libs/:$LD_LIBRARY_PATH
exec ./MyJavaApp $*

Categories

Resources