JNI issue on Linux: cannot open shared object file - linux

I've seen this question on here, tried the proposed fixes, but no success so far for me. I have quite some Java experience, but JNI is a long time ago, never did it on Linux though...
I'm trying to get a simple HelloWorld JNI app running on Linux.
Small java file:
class HelloWorld {
private native void print();
public static void main(String[] args){
new HelloWorld().print();
}
static {
System.out.println(System.getProperty("java.library.path"));
System.loadLibrary("HelloWorld");
}
}
Small C file:
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
return;
}
compiled the C file by:
gcc -shared -Wall -fPIC HelloWorld.c -I/usr/lib/gcc/x86_64-redhat-linux/3.4.3/include/ -o libHelloWorld.so
Run the app by:
java HelloWorld
or
java -Djava.library.path=/home/nxp40954/jnitesting/. HelloWorld
But no good, getting a:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/nxp40954/jnitesting/libHelloWorld.so: /home/nxp40954/jnitesting/libHelloWorld.so: cannot open shared object file: No such file or directory
Strange, because there is actually a /home/nxp40954/jnitesting/libHelloWorld.so file.
Does anyone have a clue?

execute this way:
export LD_LIBRARY_PATH=.
java HelloWorld
The java.lang.UnsatisfiedLinkError is thrown when the .so file cannot be loaded.
The LD_LIBRARY_PATH variable points extra location to look for the *.so files.
I'm on 32bit ubuntu with sun java. I was compiling this way:
gcc -shared -Wall -fPIC HelloWorld.c -I/usr/lib/jvm/java-6-sun-1.6.0.26/include -I/usr/lib/jvm/java-6-sun-1.6.0.26/include/linux -o libHelloWorld.so

Your example worked for me on a 32-bit Linux installation.
Is your shared library compiled as a 32-bit or 64-bit shared library? Check with command file libHelloWorld.so. If your shared library is 64-bit then you need to give command line option -d64 when starting Java so that Java can load the 64-bit shared library.
If your shared library is 32-bit then perhaps the Java option -d32 will solve the problem.

Clarification on java.library.path and system path:
java.library.path is a JVM-Variable which can be set - e.g. - by the command line parameter
-Djava.library.path=xy
DLL's (on windows) and so's (on linux) which are loaded by the java call loadLibrary() must be located in the java.library.path. If it is loaded via JNI it must be located in the system path.
If such a linked library loads another linked library, latter must be found in the system path. In Windows the system path is resolved against the PATH environment variable, in linux it's the LD_LIBRARY_PATH environment variable (for linked libraries).
Another point to ensure in linux: Verify that the linked library has executable permissions for the current user. Usually a
sudo chmod 755 myLinkedLib
does the trick.

Related

linking fortran code to library

I'm trying to link my main code to a library
main code:
program main1
call test1
end program main1
library:
subroutine test1
print*,'ok'
end subroutine test1
then I create library :
gfortran -shared -fPIC -o lib1.so 1.f90
and compile main code
gfortran -c main.f90
and link
gfortran main.o lib1.so
but I've got this error :
./a.out: error while loading shared libraries: lib1.so: cannot open shared object file: No such file or directory
what am I doing wrong?
your example does work, but you are just missing a small thing: When using a shared library, your program (main.f90 / a.out) will try to find the linked library in one of the library folders (such as /lib*, /usr/lib* or /usr/local/lib*).
If you want to specify another folder for your shared library (for example for testing/debugging), you can use the enviroment variable LD_LIBRARY_PATH to "tell" linux another place to look for shared libraries.
So, assuming you wrote your program in the folder /home/mojijoon/fortran you can get the correct output after setting the library path by:
$: export LD_LIBRARY_PATH=LD_LIBRARY_PATH:/home/mojijoon/fortran
$: ./a.out
ok
You can find more information on shared libraries (and the LD_LIBRARY_PATH enviromental variable) here:
tldp.org - shared libraries

cross-compiling c++11 threads with mingw on linux

I try to crosscompile some c++11 source with mingw on linux for windows. The code uses std::thread.
When i compile i always get some errors:
$ ../mingw/cross/bin/i686-w64-mingw32-g++ -std=c++11 -I include/ test.cpp -lstdthread -otest
In file included from test.cpp:4:0:
...
error: 'thread' in namespace 'std' does not name a type
...
I it possible to enable c++11 threads in mingw? The code compiles without any problems with the local g++.
Thank you,
regars
Kevin
-edit-
I just downloaded the mingw somewhere in the internet, because i tried to get an as new as possible version:
../mingw/cross/bin/i686-w64-mingw32-g++ -v
Using built-in specs.
COLLECT_GCC=../mingw/cross/bin/i686-w64-mingw32-g++
COLLECT_LTO_WRAPPER=/home/bmeier/source/mingw/cross/bin/../libexec/gcc/i686-w64-mingw32/4.8.1/lto-wrapper
Target: i686-w64-mingw32
Configured with: /home/drangon/work/mingw-w64-dgn_32/source/gcc-4.8.1/configure --target=i686-w64-mingw32 --disable-nls --disable-multilib --with-gmp=/home/drangon/work/mingw-w64-dgn_32/build/for_cross --with-mpfr=/home/drangon/work/mingw-w64-dgn_32/build/for_cross --with-mpc=/home/drangon/work/mingw-w64-dgn_32/build/for_cross --with-isl=/home/drangon/work/mingw-w64-dgn_32/build/for_cross --with-cloog=/home/drangon/work/mingw-w64-dgn_32/build/for_cross --enable-languages=c,c++,objc,obj-c++ --disable-libstdcxx-pch --prefix=/home/drangon/work/mingw-w64-dgn_32/cross --with-sysroot=/home/drangon/work/mingw-w64-dgn_32/cross
Thread model: win32
gcc version 4.8.1 (GCC)
regards
Kevin
There is already a native implementation of std::thread and sync primitives, that works with any C++11 version of MinGW:
https://github.com/meganz/mingw-std-threads
Basically MinGW does not support threads on windows see the following link: http://www.cplusplus.com/forum/windows/82461/
Specifically _GLIBCXX_HAS_GTHREADS is not defined and the class thread in the header thread requires it. (It is built on gthreads).
You should try and use boost::thread for a win/linux compatible thread class
Most probably you might have forgot to include thread header #include <thread>

Can't Access sys/socket.h using Cygwin

I need to compile C/C++ pthread and socket code in windows 8 where I've installed MicGW GCC and G++ 4.7.
When I compile my test code using g++ test.cpp -o test
Code is:
#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
using namespace std;
int main() {
cout<<"Got Socket";
}
This gives error fatal error: sys/socket.h not found and the
same occur with types.h
The error I found is that cygwin is using MicGW GCC and g++ but I want it to use its own instead of MinGW's so that I can include Linux libraries.
I have not been able to reproduce your problem on my Cygwin.
Are the headers present in /usr/include/sys?
Search the sys folder in [installed directory]/usr/include if the socket.h was not there download one Copy it there manually.
don't afraid of manual works ;-)

How to make OpenMP work with MinGW-64 under Cygwin?

The Scenario
I am developing an application in C99 ANSI C that uses OpenMP and GMP. It's natural habitat will be a linux machine with plenty of cores, so there's basically no big trouble there, but for reasons I do not want to debate here, I have to develop under Cygwin on a 64 bit Windows machine.
When I use the 32 bit version of gcc, something, somewhere, goes horribly wrong and the application is about 60 times slower than a very crude single-threaded version, when it should in fact be faster by a factor that equals the number of CPU's. It makes it impossible to work with. I really don't know what is causing this; Anyway, I have decided to use the 64 bit version of MinGW instead, that'd be x86_64-w64-mingw32-gcc-4.5.3 and his friends, to be precise.
A side note: I am sure that the slowdown is not a flaw in my multithreading, the multithreaded application works correctly and faster on the linux machine.
The actual Problem
Setting up GMP was easy, it can be compiled from source without any trouble and then works like a charm. Compiling the following easy example with -fopenmp also works like a charm:
#include <gmp.h>
#include <omp.h>
int main() {
#pragma omp parallel
{
mpz_t t;
mpz_init(t);
mpz_set_si(t,omp_get_thread_num());
# pragma omp critical
{
gmp_printf("Hello From GMP'd Thread %Zd!\n",t);
fflush(stdout);
}
mpz_clear(t);
}
return 0;
}
However, executing it gives me
$ ./test
test.exe: error while loading shared libraries: ?:
cannot open shared object file: No such file or directory
I am aware of this question, but I would like to make this work without downloading any binaries other than those from an official Cygwin repository. Since my example compiled with the -fopenmp switch, I am convinced that this should also be very much possible.
Can someone help me with that? Thanks a bunch in advance.
I think that "error while loading shared libraries: ?:" means that cygwin does not know where to find libgmp-10.dll and/or libgomp-1.dll.
Both DLL are required according to Dependency Walker
Your program worked after I added the directory that contains both DLL to my PATH:
#$ x86_64-w64-mingw32-g++ -fopenmp -o w64test gmp_hello.c -lgmp
#$ file ./w64test.exe
./w64test.exe: PE32+ executable (console) x86-64, for MS Windows
#$ ./w64test.exe
/home/david/SO/hello_openmp/w64test.exe: error while loading shared
libraries: ?: cannot open shared object file: No such file or
directory
#$ ls /cygdrive/c/dev/cygwin/usr/x86_64-w64-mingw32/sys-root/mingw/bin/*mp*dll
/cygdrive/c/dev/cygwin/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgmp-10.dll
/cygdrive/c/dev/cygwin/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgomp-1.dll
#$ export PATH=$PATH:/cygdrive/c/dev/cygwin/usr/x86_64-w64-mingw32/sys-root/mingw/bin/
#$ ./w64test.exe
Hello From GMP'd Thread 1!
Hello From GMP'd Thread 0!
note
I compiled and installed gmp-5.0.5 with the following commands:
./configure --build=i686-pc-cygwin --host=x86_64-w64-mingw32 --prefix=/usr/x86_64-w64-mingw32/sys-root/mingw --enable-shared --disable-static
make -j 2
make check
make install
update
Your program also works with cygwin "GCC Release series 4 compiler".
#$ g++ -fopenmp -o cygtest gmp_hello.c -lgmp
#$ ./cygtest.exe
Hello From GMP'd Thread 1!
Hello From GMP'd Thread 0!
#$ g++ -v
Target: i686-pc-cygwin
Thread model: posix
gcc version 4.5.3 (GCC)
You might need to install the following packages:
libgmp-devel (Development library for GMP)
libgmp3 (Runtime library for GMP)
libgomp1 (GOMP shared runtime)

static build glew & glfw on linux

In my project directory, i have:
./external/glew, which has glew compiled from source (ran make)
./external/glfw, which has glfw also compiled from source (ran make x11)
in my .c source code:
#include <stdio.h>
#include <stdlib.h>
#include "external/glew/include/GL/glew.h"
#include "external/glfw/include/GL/glfw.h"
i tried to compile using GCC:
gcc test1.c -o test1 -DGLEW_STATIC -L./external/glew/lib -lGLEW -lGLU -lGL \
-L./external/glfw/lib/x11 -lglfw
./external/glew/lib is where the libGLEW.a is and ./external/glfw/lib/x11 is where the libglfw.a is.
and it compiles without error. but then i try to run ./test1 it gives me:
./test1: error while loading shared libraries: libGLEW.so.1.6: cannot
open shared object file: No such file or directory
how do i compile glew & glfw statically?
EDIT 1 Thanks for the help guys. After some help from people in stackoverflow and old nabble I manage to write it down what needs to be done to statically linked GLFW and GLEW and put it on http://www.phacks.net/static-compile-glfw-and-glew/
Static libraries are not linked with -l… but just added to the linker source files. However please double check you really want to link those statically. The problem you have here is that the dynamic linker on *nix systems will by default only look into the system library directories and the path specified in the LD_LIBARY_PATH environment variable.
However it is possible to add relative linker paths to the executable, where libraries are located, too (--rpath linker option). That way you can ship the libraries in a directory relative to your executable, independently from the system libraries. If you do this, you also should look into binreloc

Resources