UnsatisfiedLinkError, but library is in path - java

I'm a little confused by this error. I'm new to Java and the error seems pretty self explanatory, but I've checked my paths (even defined my own) and it still fails to find this library. Is there something I'm doing wrong? See directory screenshot and error screenshot below:
UPDATE
UPDATE 2
If I create a new NetBeans project this works fine. Same code and everything. If I create new IntelliJ project I get this error above. I must be missing something in IntelliJ
UPDATE 3
Found the solution. Adding dependencies is a bit different in IntelliJ. Thanks all for the help.
http://www.jetbrains.com/idea/webhelp/configuring-module-dependencies-and-libraries.html

Obidisc4j is a .jar file. You just dont see its extension in the explorer.
Regular jar files are not loaded by System.loadLibrary. They are automatically loaded by the JVM's classLoader.

You are using a native library. It doen't matter if that library is in the classpath. There are 4 ways you can make the Java runtime load your shared library at runtime:
Call System.load to load the .so from an explicitly specified absolute path.
Copy the shared library to one of the paths already listed in java.library.path
Modify the LD_LIBRARY_PATH environment variable to include the directory where the shared library is located.
Specify the java.library.path on the command line by using the -D option.

Seems like your application is trying to find out a obidisc4j.dll (for Windows) or obidisc4j.so (for Linux). The file must be present on the PATH (but not the classpath). If you are not sure what PATH is your Java application searching in, you can write the following statement, before the point where the exception takes place, to find out the PATH.
System.out.println(System.getProperty("java.library.path"));
This will tell you about the paths where your DLL or SO file should be placed. You just need to place the file in ONE of those N-paths.

Related

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.

Exporting a runnable jar, opening it returns an UnsatisfiedLinkError

I currently wrote a simple GUI in Eclipse which runs as intended. I was hoping to export it so I can share it with my friend (who doesn't need to install eclipse and the java libraries). I tried all 3 library handling method Eclipse provides and none of them works. I read a little online and saw something about a manifest file, but wasn't quite sure what to do with it. Is it going to help?
This is where I placed the folder that comes with the .dll file.
This is the result. Am I doing something wrong?
As indicated by the error messages in the first screenshot, what you are missing here is the native library - the software library written and compiled to native code specific to the operating system. What you will need to do is provide the libraries specific to the operating system on which your software will run, eg. dlls for 32 or 64 bit Windows. The manifest does not provide the capability to include those libraries.
When the program is run on Windows, Java will look for native libraries in the following locations:
The current directory
The directories in the PATH environment variable
The directories in java.library.path (if it's specified)
It may be easiest to simply put all files in the one directory. If you do this, you should be able to run the program in the same way as you do now.
The java.library.path option is only needed if you want to put your native library files in a directory separate to the one in which you run your program and not on your PATH. It is only in this case that you will need to add java.library.path, eg. by adding -Djava.library.path=c:\path\to\your\lib after java. Also note that you may use a relative path, ie. a path that is relative to the directory you are in when you execute the command.
I also see from your later error messages that you have another dependency, but on a java library LeapJava.jar. As running a jar with -jar will only work if you have a single jar, but because you have more than one (your own program plus the dependency), you'll instead need to use the -classpath (or -cp for short) argument and add your main class. The classpath argument is a semicolon-separated list of classpath locations, while the main class is the one containing your public static void main method, eg. your.package.name.YourMainClass. So assuming your UI.jar is still in C:\Users\Ian\Desktop\Leap Data UI, you should be able to navigate to that directory and execute with:
java -cp UI.jar;UI_lib\LeapJava.jar -Djava.library.path="UI_lib\x64" your.package.name.YourMainClass

How automatically set Native Library Path and JAR's path through code

I was trying to automatically set the native library path and the JAR's path automatically during the runtime of a program of mine (in other words, I would like to perform the settings' definition through code.
I tried to execute the following in the beginning of my program flow:
System.setProperty("java.library.path", "\\some_folder");
apparently this should set up the native library path, but the application could not load the dlls in the folder. I've also tried some variations (like "jni.library.path") but none of them seemed to work. Is there another way to solve this?
The java.library.path is read only once when the JVM starts up. If you change this property using System.setProperty, it won't make any difference. the following blog provides options to load dlls in runtime.
http://fahdshariff.blogspot.jp/2011/08/changing-java-library-path-at-runtime.html

UnsatisfiedLinkError Exception [duplicate]

I am using Jacob jar file in my java application.
This Jacob jar file comes with a .dll file. I have added Jacob jar file to my classpath. But when I execute my application a runtime error occurs as
"couldn't load jacob-1.15-M3-x86.dll file"
How can I load this .dll file?
Edited:=================================================================================
I had set the "path" environment varaible to the dir that contains my .dll file and loading that .dll file as follows
static {
System.loadLibrary("jacob-1.15-M3-x86.dll");
}
but the following error occured
java.lang.UnsatisfiedLinkError: no jacob-1.15-M3-x86.dll in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at TemplateClass.TemplateClass.<clinit>(TemplateClass.java:14)
The 'jacob-1.15-M3-x86.dll' needs to be in a place where your the operating system can find it. You have a few options here:
You can place the .dll file in the directory you started your application from. If you have a batch script to start your application, it would be that directory. If you are starting in some sort of application server, it would typically be the 'bin' directory.
You can place the .dll file somewhere in the %PATH% environment variable. I may be easier to just update your PATH environment variable to include the directory that contains your .dll file.
Another option is to place your .dll into the %SystemRoot%\system32 directory. Usually this is 'C:\Windows\system32'. This option is not usually recommended unless it is a shared library like the MSCVRT runtime.
One other possible issue you might have. If the .dll is compiled as 32-bit, then you must be running in the 32-bit Java runtime. Likewise, if it is a 64-bit .dll it needs to be run in a 64-bit JRE.
Ah, that's not a compilation error but a runtime error.
My guess would be that your DLL needs to be on the PATH. Not CLASSPATH, but PATH, because that's where Windows looks for DLLs. Try either extending your PATH to include the location of your DLL, or do what many other people do: Dump the DLL into \Winnt\System\System32 or whatever the system directory is called on your box. Wherever all the other DLLs are, in other words.
Update
The error message you post, thankfully, is pointing out the exact problem. You can solve it by putting the directory containing your DLL into java.library.path This Sun forum thread shows a nice example: http://forums.sun.com/thread.jspa?threadID=627890
Actually, that's a lot less clean than it should be; this seems to be one of the "shadier" areas in Java. The thread wanders around a lot, I do advise you to read all the way through to see some problems and solutions. I think you'll be able to succeed with a little trial and error.
Other options :
set the property java.library.path to the directory containing the dll. Example :
java -Djava.library.path="path/to/directory/containing/the/dll" -jar appli.jar
in the code, load the dll explicitly, with System.load.
You need to set LD_LIBRARY_PATH. This will give you all the right steps to follow.
When you use System.loadLibrary() don't include the .dll at the end.
Also, if you are not setting java.library.path to point to the folder containing the DLL then the DLL should be in the directory where you launch your Java application from.
I had the same problem.
I see that the question is not "answered", so maybe none of the options above worked.
One of my last hypothesis was that the Jacob.dll is missing its dependency.
What I did was to get depend and check if all the dependence, used by Jacob are loaded.
Of course this works for Windows.
Cheers!

sigar-amd64-winnt.dll ... can't reference it or bundle it with .jar

(It might be an obvious mistake I'm making, but I couldn't get it to work after 6 hours now.)
I'm trying to get CPU information using the sigar.jar in my eclipse project (just testing the sigar API for now).
It runs in eclipse without problems:
what made it work in eclipse was to put the dll in the same folder as
the sigar.jar
I tested that adding a path to the dll as the "native code property"
in the build path config dialog has no effect.
Adding vm arguments in the run configuration also has no effect.
I tested putting 2 fake paths in those 2 places and as long as I have the
dll in the same folder as the sigar.jar... it runs well in eclipse.
The problem is when I try to export a runnable .jar file for my project. I tried 2 things:
I modified the MANIFEST.MF file with Bundle-NativeCode: libs/sigar-amd64-winnt.dll (I'm assuming here the path is relative to the project folder) --> no success:
main starting!! no sigar-amd64-winnt.dll in java.library.path
org.hyperic.sigar.SigarException: no sigar-amd64-winnt.dll in
java.library.path
at org.hyperic.sigar.Sigar.loadLibrary(Sigar.java:172)
at org.hyperic.sigar.Sigar.<clinit>(Sigar.java:100)
at CpuData.main(CpuData.java:59)
cpudata(sigar s) starting!!! cpuInfo() starting!!!
Exception in thread
"main" java.lang.UnsatisfiedLinkError:
org.hyperic.sigar.Sigar.getCpuInfoList()[Lorg/hyperic/sigar/C puInfo;
at org.hyperic.sigar.Sigar.getCpuInfoList(Native Method)
at CpuData.cpuInfo(CpuData.java:103)
at CpuData.<init>(CpuData.java:29)
at CpuData.main(CpuData.java:59)
Then I decided to put the .dll in the same folder as my project.jar, and used in the command line: java -Djava.library.path=./native/ -jar C:\cpu_usage_log\cpu3.jar (I'm assuming here the path is relative to the folder that contains the project.jar) ...but again no success:
Error: impossible to find or load the main class .library.path=..native
(I suspected that I should give a main class name as a second argument after the -Djava.library.path=./path/ but I can't find that supposed "main class" name, or any examples on the web that do specify such a class ...is it a main class from within the .dll?)
I don't really know what else to try at this point. I read those 2 solutions worked for others, and it makes it even more frustrating because I imagine it could something obvious that I missed or didn't understand when reading other posts and that I just can't find (it's the first time I deal with native dlls in a java project).
For me it was always the best to modify the way how Java loads the library.
Usually you call System.loadLibrary("mylib"); which searches the library on the library path.
IMHO it is much better loading the library using it's absolute path. This allows you to implement a custom search logic in your program:
// Extends the name to mylib.so or mylib.dll
mylibname = System.mapLibraryName("mylib");
// Load the library via its absolute path
System.load(new File(path, mylibname).getAbsolutePath());
Note that each library can only be loaded once, therefore if you load the library as shown above, calls of System.loadLibrary("mylib"); afterwards will be ignored as the library is already loaded.

Categories