Jna path resolving - java

Im trying to use GStreamer in eclipse via jna.
Processing provides a library for that and all is fine if i try to run the code by running the sketch as an applet from eclipse, but when i try to execute the whole application i get a list of warnings(on Camera first call) like this one
(javaw.exe:3840): GStreamer-WARNING **: Failed to load plugin 'C:/Users/aaa/Desktop/bbb/ccc/video/library/\windows64\plugins\libgstvorbis.dll': `C:/Users/aaa/Desktop/bbb/ccc/video/library/\windows64\plugins\libgstvorbis.dll': Impossibile trovare il modulo specificato.
on 30+ of 140 plugins (probably the ones needed by my library for the camera managment)
the jna jar and the libraries are in the project folder C:/Users/aaa/Desktop/bbb/ccc/video/library/
and included in the build path
and the native code is in C:/Users/aaa/Desktop/bbb/ccc/video/library/windows64/plugins/
the path doesnt seem correct...
i never wrote libraries that need jna and i was trying to use this library as is if possible, any suggestions?

You can set the system property jna.library.path to the path to your primary library that is being loaded. All of that library's dependencies must either be in that directory or on %PATH%.
You can find the dependent libraries using dependency walker.

Related

still experiencing linker error despite linking the java jar file in visual studio code

I am trying to build a small personal project with opencv. I included the path to the opencv jar file in visual studio using the java dependencies then referenced libraries but i get the linker error: Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java430 in java.library.path. I have no idea what else i could do
UnsatisfiedLinkError isn't about jar files.
It's about 'native' files. These are generally stored as a .jnilib file on mac, as a .DLL on windows, and as a .so file on on most unixen.
They cannot be in jar files.
Some libraries will put in some effort and ship a whole bevy of them (as each architecture and OS has a unique dll/jnilib/so file that is needed) inside the jar, will find the 'right' one for your arch/os combo, unpack it someplace, and try to load it live.
This is either not working, or this library isn't doing that. Presumably the opencv site contains a tutorial on how to get it running; as native files are required, it's a bit more involved than 'just download, add to classpath, and voila'. I suggest you follow it precisely.
If you do have something that seems suitable (probably called opencv_java430.dll or whatnot), start java with java -Djava.library.path=/directory/containing/that/file the.rest.of.your.java.args - that should help.

OpenCV 4.3.0 java.lang.UnsatisfiedLinkError in Eclipse

I'm trying to do some template matching with the Java binding of OpenCV 4.3.0 in Eclipse, but attempting to load the template image always results in this error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.imgcodecs.Imgcodecs.imread_0(Ljava/lang/String;I)J
The line of code where this exception is thrown is this:
flowerTemplate = Imgcodecs.imread("/templates/flowerpot_white.png", Imgcodecs.IMREAD_COLOR);
I have tried a number of solutions suggested on similar questions on StackOverflow and elsewhere on the internet, including:
Pointing at the native library folder with the "Native library location" variable in the user library definition in Eclipse.
Adding the native library folder location to my PATH variable.
Adding the native library .dll location to my PATH variable.
Setting up the Eclipse run configuration to add the native library folder & .dll locations to the PATH and CLASSPATH variables.
Loading the library with the appropriate Java code, in each of the three ways I saw it suggested, in three different places which all run before the code that throws the exception.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.load(<path_to_the_dll>);
File opencvLibrary = new File(System.mapLibraryName(Core.NATIVE_LIBRARY_NAME));
System.load(opencvLibrary.getAbsolutePath());
Placing the .dll in question into my source folder and every subfolder. I am running it from within Eclipse, so this is also the program's working directory.
UnsatisfiedLinkError is a runtime exception that happens when running your Java program. So placing your file in the source folder will not work.
You need it to be available in a place that your program can find it.
See this article for example:
https://www.javaworld.com/article/2077520/java-tip-23--write-native-methods.html
In it they place the library in Linux's library path. In windows you'd similarly place it in the current directory (where you're running from) or in some shared location.
This article explains Window's dll search order: https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
You shouldn't need to explicitly call System.loadLibrary() yourself. That's the library's responsibility.
Your problem is that OpenCV is improperly installed on your machine or inaccessible from Eclipse.
For instructions on how to make in work in Eclipse see:
Add .dll to java.library.path in Eclipse/PyDev Jython project
After removing every load method and then adding them back one-by-one, I determined that the issue was most likely caused by Eclipse loading the native library folder twice.

Issues loading .so file with JNA in Spring Boot on Linux

I have an application written in Java with Spring Boot. This application needs to load .so files that are bundled with the project, I am using JNA to accomplish this. However, the JNA loader doesn't seem to be able to pick up the .so files and the application fails to start.
I've tried running the application from within IntelliJ and by running the packaged .jar with "java -jar". The .so files are kept in src/main/resources/linux-x86-64 for now. I've tried keeping them in a different directory, e.g src/main/resources/libs/linux-x86-64 and set the property "jna.library.path", but JNA still fails to find the files.
This is the debug log for JNA:
Trying (via loadLibrary) jnidispatch
Looking in classpath from sun.misc.Launcher$AppClassLoader#18b4aac2 for /com/sun/jna/linux-x86-64/libjnidispatch.so
Found library resource at jar:file:/home/dalivi/.m2/repository/net/java/dev/jna/jna/4.5.0/jna-4.5.0.jar!/com/sun/jna/linux-x86-64/libjnidispatch.so
Trying /tmp/jna--1339148563/jna4246531844315283838.tmp
Found jnidispatch at /tmp/jna--1339148563/jna4246531844315283838.tmp
Looking for library 'GTransTF'
Adding paths from jna.library.path: null
Trying libGTransTF.so
Adding system paths: [/usr/lib/x86_64-linux-gnu, /lib/x86_64-linux-gnu, /lib64, /usr/lib, /lib, /lib/i386-linux-gnu, /usr/lib/i386-linux-gnu, /usr/lib/x86_64-linux-gnu/libfakeroot]
Trying libGTransTF.so
Looking for version variants
Looking in classpath from sun.misc.Launcher$AppClassLoader#18b4aac2 for GTransTF
Found library resource at file:/home/dalivi/Workspace/java/geotransboot/target/classes/linux-x86-64/libGTransTF.so
Looking in /home/dalivi/Workspace/java/geotransboot/target/classes/linux-x86-64/libGTransTF.so
2019-04-25 12:43:38.032 ERROR 25897 --- [o-auto-1-exec-1] s.l.g.c.TransformationRestController : Handler dispatch failed; nested exception is java.lang.UnsatisfiedLinkError: libCoreGTrans.so: cannot open shared object file: No such file or directory
I does seem to find one of the files in the directory: libGTransTF.so, but then immediately fails when trying to find the file libCoreGTrans.so which is present in the same directory as the previous file.
I should mention, on Windows, this works just fine. JNA finds the corresponding dll files in the directory specified with "jna.library.path".
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:
ldd ./libGTransTF.so
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:
-Wl,-rpath,'$ORIGIN'
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
Then when you run:
ldd ./libGTransTF.so
it should be able to successfully find the libCoreGTrans.so library.

How to use a JNI lib, with associated libs, at an arbitrary location?

We have an app that sometimes is installed with an associated app. Both may be installed separately, at different times, and neither is usually in the OS Path environment setting.
IF both apps are installed, the one I'm working on needs to use a JNI library from the other app. This library uses a dozen or so other native libs. While I can FIND the JNI lib, I can't seem to find a way to use it without requiring the user to change their system setup.
I've found the (hacky) technique to add the JNI lib to the java.library.path, I've been unable to find any way of updating the native Path so the JNI lib can find it's associated libs.
The only things that have worked so far are to:
Add the folder that the JNI and associated files are in to the OS path before launching our app.
Launch our app so the Current Working Directory is the JNI lib folder.
Neither of which makes for a hassle-free user experience.
So, is there any way for a Java app to modify it's own environment Path so the JNI lib can find it's associated native libs? (currently testing on Win7, will also need to support OS/X)
This can not be done with an unknown location at run time. According to jni documentation
"To load your shared native library module in Java, simply use Java's System.loadLibrary method in a Java class:"
as well as
"Another common reason for the native library not loading is because it is not in your path. On Windows make sure the path environment variable contains the path to the native library. On Unix make sure that your LD_LIBRARY_PATH contains the path to the native library. Adding paths to LD_LIBRARY_PATH can slow down other programs on your system so you may want to consider alternative approaches. For example you could recompile your native library with extra path information using -rpath if you're using GNU, see the GNU linker documentation (ld man page). You could use a command such as ldconfig (Linux) or crle (Solaris) to add additional search paths to the default system configuration (this requires root access and you will need to read the man pages)."
So thus you need to know the location and must be in a path to be able to load the file. If the location is not known it can not be done due to how jni works and the jvm works.
One way to load a JNI lib with dependent libraries is to load each of the dependents then load the JNI library.
For example, if bar.so is dependent on foo.so and both libraries exist in /some/dir, do the following:
System.load("/some/dir/foo.so");
System.load("/some/dir/bar.so");
Use System.load() instead of System.loadLibrary() so you can specify the absolute path to the library.
You'll have to load all dependents of all loaded libraries unless they can be found in the java.library.path path.
Hope this helps.

Installation of custom made shared library files/ Or any alternatives to it

I have an app(for CentOs) that uses two custom made shared libraries "libMyInit.so" (linked with libMyInit.so.1 and libMyInit.so.1.0.1) and libMyUtil.so (linked with libMyUtil.so.1 and libMyUtil.so libMyUtil.so.1.0.1). Thes are present inside the app packaging like MyApp/bin/libMyInit.so & MyApp/bin/util/libMyUtil.so along with their respective linked libraries.
When I have to run the app I have to explictly add the above mentioned paths to LD_LIBRARY_PATH without which it give the error like:
ERROR:Unable to load native MyUtil library. Reason: no MyUtil in java.library.path.
Is there any way I can avoid the manual adding of libraries to LD_LIBRARY_PATH ?
Something that I can do at compile time of shared libraries or later so that the custom made .so libraries are found in the java.library.path ?
IMHO the best way of doing this, is to use a custom System.loadLibrary in the static part of your classes. Have a look at my Java portaudio bindings here#github, especially at the LoadLibrary and JPA classes.
The LoadLibrary class selects a native library based on OS type and architecture, unpacks the lib from its JAR into the temp folder and loads it from there.
JPA now just has to call LoadLibrary.load and everything works automagically on all supported OSs and you only need one single JAR file.
One of the ways is to copy those libraries to one of /usr/lib, /lib, /usr/local/lib directories.

Categories