- Including the *.SO library to the Java project (Linux)
- 1 Answer 1
- Loading a linux so file at java runtime
- Loading a Linux .so File at Java Runtime
- How to add .so file to the java.library.path in Linux
- Load shared library by path at runtime
- Issues loading .so file with JNA in Spring Boot on Linux
- How to Use Linux Shared Libraries in Java
- How to link shared library to another shared library
- Java: load shared libraries with dependencies
- Shared library on Linux does not contain reference to one of its dependencies
- Java program that access C++ shared library that uses OpenCV
- How can I use Linux shared libraries in Java?
- 3 Answers 3
- Linked
- Related
- Hot Network Questions
- Subscribe to RSS
Including the *.SO library to the Java project (Linux)
I am not a Java developer, but I need to solve a problem: I need to include linux SO library to an existing Java project. The library is developed using CGO and works fine with C++, Python ctypes, Ruby FFI and so on. But I can not include it to Java project without of errors (java.lang.UnsatisfiedLinkError). I have read some articles like this, and the described method is that I need use javah to create a C header first, and then write a C program, and so on. But what to do, if I have already compiled *.SO file? Is there a way, how to simply load an existing SO file (written on C) and call it`s functions?
Java is platform independent, that said, maybe read up on JNI? E.g. medium.com/@bschlining/… What I had to do on Windows was to write my own DLL, which called a thrid party DLL. That way I could do the whole h file thing
1 Answer 1
Java doesn’t have builtin FFI functionality.
One option for using native libraries (.dll/.so) with Java is to write a JNI wrapper library that has special functions that can be bound to Java native methods. That’s the option where you need to use javah to create a header file for the wrapper library. See the «Java Native Interface» documentation on Oracle’s site for how to do that.
The other approach is to use a «glue» library like JNA. You don’t need to build another library this way but you need to include JNA in your project and do the necessary Java declarations for it. You can find the documentation for JNA in the Github repository together with the code. That approach is similar to what Python, Ruby, etc. are doing.
I recommend reading up on both to see what will better suit your needs.
Loading a linux so file at java runtime
Solution: The windows behaviour is to search for dependent libraries in the directory that the comes from, so when jna loads the library into memory the dependent library is loaded from there as well. You can add an option to the library when building to search in specific locations to find libraries.
Loading a Linux .so File at Java Runtime
Libraries on Linux are often named in the pattern libXXX.so , and I believe Java follows that convention. So System.loadLibrary(«Sample») may be looking for libSample.so . You can verify this by making a quick test program to call System.mapLibraryName and checking the output.
To resolve the issue, assuming this is in fact the problem you’re having, you can either rename your library file or use System.load (not System.loadLibrary ), which will load the library specified by the exact filename you pass it, without any transformations. The latter method is not portable across platforms, though.
Runtime.getRuntime().load(resource);
I faced the same issue in Linux and solved by setting the LD_LIBRARY_PATH variable
export LD_LIBRARY_PATH=:$LD_LIBRARY_PATH.
C — cannot open shared object file: No such file or directory, You should add the libbpf library directory to your LD_LIBRARY_PATH variable. $ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/build/root/usr/lib64
How to add .so file to the java.library.path in Linux
Add the containing directory to LD_LIBRARY_PATH before launching the application
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/some/pathOfContainingDirectory
Use java -XshowSettings:properties to show the java.library.path (and others) value.
I had a lot of trouble figuring this out, please make sure that you have lib prefix in the library name.
- export LD_LIBRARY_PATH=»$LD_LIBRARY_PATH:/some/pathOfContainingDirectory»
- Rename libraries to have lib as a prefix. [Add this as part of build script]
mv JNIDemo.so libJNIDemo.so
Check this answer for detailed explanation https://stackoverflow.com/a/3987567/2076566
I used java -XshowSettings:properties method and found the path of a previously set folder and copied my so file to that folder
Cannot open shared object file: No such file or directory, Your library is a dynamic library. You need to tell the operating system where it can locate it at runtime. To do so, we will need to do those easy steps:.
Load shared library by path at runtime
Un UNIX/Linux systems you can use dlopen . The issue then is you have to fetch all symbols you need via dlsym
typedef int (*some_func)(char *param); void *myso = dlopen("/path/to/my.so", RTLD_NOW); some_func *func = dlsym(myso, "function_name_to_fetch"); func("foo"); dlclose(myso);
Will load the .so and execute function_name_to_fetch() from in there. See the man page dlopen(1) for more.
On Windows, you can use LoadLibrary , and on Linux, dlopen . The APIs are extremely similar and can load a so/dll directly by providing the full path. That works if it is a run-time dependency (after loading, you «link» by calling GetProcAddress / dlsym .)
I concur with the other posters about the use of dlopen and LoadLibrary. The libltdl gives you a platform-independent interface to these functions.
Java — Running JAR file from terminal (Runtime.getRuntime().exec, You can’t use -jar and -cp at the same time. What you can do, is adding your jar to the classpath and then specify your Main class to run.
Issues loading .so file with JNA in Spring Boot on Linux
The windows behaviour is to search for dependent libraries in the directory that the .dll comes from, so when jna loads the library into memory the dependent library is loaded from there as well.
If you fire up a terminal window and cd to the directory that the .so exists in and run the command:
and it indicates that it’s unable to find the library libCoreGTrans.so then you can see that the search order won’t find this location.
The run-time link-loader ( ld.so ) uses a set of decisions as to where to find libraries. The default behaviour doesn’t include the directory that the library was found.
You can add an option to the library when building to search in specific locations to find libraries. When you’re building the library, you can say to search in the directory that the .so comes from at run time by adding the line:
to the link line. It needs to populate with the constant value $ORIGIN or else this doesn’t work, so this can be a bit tricky to get right in a makefile. This is a value that gets resolved at run-time.
This is all very fine and well if you’re building the library yourself, but if you’re getting libraries from somewhere else, or you’ve already built them and don’t want to rebuild them, you can use a tool such as patchelf to edit the search path for an .so to add it’s origin location:
patchelf --set-rpath '$ORIGIN' libGTransTF.so
it should be able to successfully find the libCoreGTrans.so library.
Loading a Linux .so File at Java Runtime, load (not System.loadLibrary ), which will load the library specified by the exact filename you pass it, without any transformations. The latter
How to Use Linux Shared Libraries in Java
How to link shared library to another shared library
$ c++filt _ZN5vatps6PosAPI8sendDataB5cxx11Ev
vatps::PosAPI::sendData[abi:cxx11]()
So, your code expects sendData with std::string with C++11 ABI, whereas libPosAPI.so provides sendData with pre-C++11 ABI std::string .
abi:cxx11 hints to GCC5 and the C++11 ABI:
Users that depend on third-party libraries or plugin interfaces that still use the old ABI can build their code with -D_GLIBCXX_USE_CXX11_ABI=0 and everything should work fine. In most cases, it will be obvious when this flag is needed because of errors from the linker complaining about unresolved symbols involving __cxx11 .
Java: load shared libraries with dependencies
I have found an acceptable solution in the end, but not without significant amount of hoops. What I do is
- Use the normal JNA mechanism to map the dlopen() function from the dynamic linking library (libdl.so).
- Use the dlopen() function mapped in with JNA to load external libraries «ext1» and «ext2» with the option RTLD_GLOBAL set.
It actually seems to work 🙂
Shared library on Linux does not contain reference to one of its dependencies
Your version of cc (or the link editor used by it) seem to default to -Wl,—as-neeeded . In this case, the command line order matters. If -lcpdf comes first, there are no references to its symbols yet, and so no dependency is created. -l arguments should come last:
cc -shared -fpic -I$JAVA_HOME/include I$JAVA_HOME/include/linux jcpdfwrapper.c -o libjcpdf.so -L. -lcpdf
Java program that access C++ shared library that uses OpenCV
According to the Makefiles in your gist, the problem seems to be that the pkg-config —libs —cflags opencv , which adds a bunch of -l library arguments to the linker, is mentioned before the objects that actually depend on those libraries. In your Makefile, the easiest fix would be to move your $(INCLUDES) reference to the end of the commands, after $(LIBS) .
How can I use Linux shared libraries in Java?
Is there any way to call the functions which are in a so library from my Java code? Generally, is it possible to use Linux so libraries in Java programs?
3 Answers 3
Here are a couple of links:
You cannot use arbitrary .so libraries in your Java code. You can use JNI to write a wrapper around native code to access from Java.
However, be aware that doing so negates many of the advantages of using Java. Your code and deployment system now becomes quite fragile and subject to many types of bugs that cannot happen in Java. I would try quite hard to find a pure-Java solution before resorting to using native code.
I agree 100%. But there are many cases when you need to access a piece of hardware that requires a native library. I am having a hard time with this. Unfortunately I already spent weeks looking for a solution (native library seems not to be loaded, sick)
Another wayto access libraries form java besides JNI is JNA.
I find that in many cases it’s easier to use then JNI, but that’s just my personal opinion.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.12.43529
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.