Can't load a .dll with System.load(path); - java

I made a Java OCR program using the AspriseOCR.
It requires a .dll called AspriseOCR.dll, I copied the dll to C:/Windows/System32/
But when I use
System.load("C:/Windows/System32/AspriseOCR.dll");
I still get a UnsatisfiedLinkError.
I've spent the last 2 days searching for a solution to my problem, but I couldn't find anything that works.
Okay everyone, it works now. Turns out I also had to make a 32-bit version!
If anyone ever needs help with the OCR Engine from Asprise, pm and I'll try to help you!

To load libraries, such as DLLs, you should use
System.loadLibrary("libname");
Where "libname" is the name of the library. You do not include the extension of the file it is stored in, or the full path to the file. For your case, you would probably call
System.loadLibrary("AspriseOCR");
to load the library you are using.
Because loadLibrary takes a library name for an argument, not a file, you must be careful where you place the .dll. Normally, you could include it in the working directory of the application, or in a native folder such as System32. If you must put it somewhere else, be sure to appropriately set java.libary.path. For example, if the .dll is in the folder "libraries", you should launch java with the argument
-Djava.library.path=libraries

Related

Java System.load(libName) looks for wrong lib name

I've run into a strange behaviour on one of our customers machine when trying to load a JNI library at runtime.
When trying to load a library with
System.load("libtestlibrary.so")
I get a
liblibtestlibrary.so.so: cannot open shared object file: No such file or directory
It seems like the given library name is (wrongly) prefixed with "lib" and suffixed with ".so" and thus our library cannot be found.
This only happens on one machine (AIX 6). I was unable to reproduce this behaviour on our own AIX 6 box using the exact same JRE, so I'm guessing this is caused by some OS settings on the customer machine.
Does anybody have an idea how to turn this off?
You can use either:
System.loadLibrary("libraryname");
It will be properly expanded to system specific notation. Or you can use:
System.load("you_can_have_anything_you_like_here")
In second case, all you need to do is to point to proper location of file. If you are looking for cross system development, you might be interested in packaging your native code inside JAR. Take a look here for a sample code where library is taken from JAR file
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031
Also, make sure that other libraries are available in LD_LIBRARY_PATH. Note that java.library.path is only valid for your "first" native lib. If your code uses some other shared libs, you have to either compile with rpath or make sure libraries are visible system wide.
Yet another approach is to go via stub: http://jnicookbook.owsiak.org/recipe-No-018/
In that case, you can load library as you like and do whatever you like (e.g. change native code on the fly).

How does a JNI DLL search for its dependent native DLL?

Say I have JNI.dll. It depends on native.dll. Now my Java application calls System.loadLibrary("JNI").
Will the following folder layout work?
MainFolder
|--main.exe
|--SubFolder
|--JNI.dll
|--native.dll
My guess is, there are 2 levels of dependency resolution.
[Level 1]:
System.loadLibrary("JNI") uses JVM property java.library.path to locate JNI.dll.
[Level 2]:
JNI.dll relies on Windows system mechanism to locate native.dll.
Is this correct?
If I set %_JAVA_OPTIONS% as -Djava.library.path=MainFolder\SubFolder, I think it can cover the search for JNI.dll. But will it cover the search for native.dll, too?
ADD 1
It seems my guess of 2 levels got confirmed from here: How to add native library to "java.library.path" with Eclipse launch (instead of overriding it)
See comment by kevin cline. But the mentioned solution with LD_LIBRARY_PATH environment variable only applies to Linux.
ADD 2
I think I didn't make my question clear. Let me put it this way.
My confusion is: the JNI.dll depends on native.dll. Both of them are not in the main.exe's current working directory. Actually they are in a sub folder of CWD.
If I run main.exe directly, I just need to set the java.library.path = <other path>\MainFolder\SubFolder. Both DLL are found correctly.
But if I run my project from Eclipse, besides setting the java.library.path, I have to put the "\MainFolder\SubFolder" in the %PATH% environment variable.
I just don't know why Eclipse is so different.
1)It searches in the current Directory.
2)System folder typically C:\Windows\System32 (use CSIDL_SYSTEM with shgetspecialfolderpath() to get the rigth folder on the given system)
3)Windows folder (C:\Windows )(CSIDL_WINDOWS with shgetspecialfolderpath() to get the right folder on the given system)
4)All the folders listed under PAth environmnet variable
A similar link: Must I place all dependent DLLs into the JDK's bin folder?
Inspired by this thread:System versus user PATH environmental variable...winmerge works only if I add the path to the user PATH
I start to wonder maybe my User %Path% is too long. So I moved the folder path containing my dependent DLL from the end of User %PATH% to the beginning. It works now!
At first, I conclude that one who implemented the Windows' DLL lookup algorithm has some truncation issue. And I almost consider it as another annoying Windows Bug.
But I wrote another Windows application which has similar DLL dependencies to confirm my guess. That application works fine! So I have to review my conclusion.
I checked my User %PATH% entry one by one, and place the folder to each possible location. And finally, I find the root cause.
I have a C:\MinGW\bin entry in User %PATH%, which happens to contain a
libstdc++-6.dll (977KB) but unfortunately, which isn't compatible
with the one I need (825KB). It only works if I place my folder before MinGW.
Now this issue seems resolved. But another one comes up, do I need to switch back and forth if I want to use both my DLL and the MinGW?

Expandable java system

I've been asked to create a java system capable of expand itself by plugins, however i'm a little confused in how exactly should i do that, my initial idea was to create a folder in the system's root path and create a routine that would read that folder and scan for .jar files that can be recognized as plugins (inside the .jar there'll be a .xml file which will be used as the system's signature), then load the files in the classpath at runtime, well this part seems quite easy, i found a lot of material about this subject, but i can't realize how i'll make the plugin access the main system's classes and methods, my initial idea was to pass through the constructor of the plugin, the path for the main system .jar and then load the main .jar in the plugin at runtime but i'm not sure if this is the most efficient approach. Does anybody has an idea?

Cannot read from an runnable Jar file

I'm trying to make a mp3 player and I used javazoom libraries. I save mp3 path in library.txt file to reopen them. There is not any problem with openning library.txt which is in the jar file.
Normally with eclipse program It is working well but when i created a jar file the problems begins.
I can't use absolute paths to open any mp3 file with my jar file.
File file = new File("/Users/orcungumus/Music/iTunes/iTunes Media/Music/Bruno Mars/Unorthodox Jukebox/1-16 16 Locked Out of Heaven.mp3");
try {
player.open(file);
} catch (BasicPlayerException e1) {
JOptionPane.showMessageDialog(null, e1.toString(),
"Error", JOptionPane.INFORMATION_MESSAGE);
}
For making thinks easier to understand i used directly path of an file. It works for eclipse, but with jar file it can't open file.
This is the error which i take:
If it is important i use mac os.
Edit: I realized that this is not about absolute path by making mp3 path relative. Libraries give an error about audio format. So, the problem is still exist. what can be the differencies between runnable jar file version and eclipse run for an project.
well, that's hard to find out.
now your problem is unable to open a audio file, which I can't handle.
However you said that the programme run perfectly using eclipse, so the question became
the different between running in eclipse and normal jar file.
FIRST, eclipse not directly use java.exe nor javaw.exe for execution. Instead, eclipse use some custom defined library in order to redirect the console, handling exception, etc.
(That is nothing to your problem)
SECOND, eclipse will set the working directory for you automatically (to the project root directory), where may contain some necessary native library.
THIRD, eclipse also define some path for native location for library, I think you may use eclipse built-in export to create the jar file which however not include the native library.
the second and third difference may help you, because they are quite effective to jar file.
I have just browsed javazoom briefly, I don't know whether there is native library. If not,
I sorry that you have to find other solution.

UnsatisfiedLinkError - Unable to load library - Native library not found in resource path

I have the following error at runtime, while trying to run Tess4J:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'libtesseract302': Native library (win32-x86-64/libtesseract302.dll) not found in resource path ([myproject/target/classes/, ...some jars...])
My questions are:
1) What exactly it tries to find and where?
2) Why is it apparently searches for myproject/target/classes/ directory? I set it nowhere.
3) Why is it ignores "native directory path" I set for tess4j.jar in user library descripto in Eclipse? My DLLs are there. If it didn't ignore the path, it would find DLLs.
4) Why is it apparently prepending DLL name with win32-x86-64/? I set this nowhere. Is this standard prefix of some API?
5) What is "resource path"? How to set it?
Like the error says, it's looking for win32-x86-64/libtesseract302.dll in java.class.path. Part of your classpath apparently includes myproject/target/classes.
The prefix represents the platform and architecture of the shared library to be loaded, which allows shared libraries for different targets to be included in the same archive. If JNA cannot find the requested library name in the system load path, then it attempts to find it within your resource path (extracting it, if necessary). So if you put the DLL in a jar file, you'll need to give it the win32-x86-64 prefix in order for it to load.
The "resource path" is nominally your class path; basically anywhere reachable by ClassLoader.getResource().
The error stems from your trying to load 32-bit DLLs in 64-bit JVM. The possible solution is switch to 32-bit JVM; alternatively, use 64-bit Tesseract and Leptonica DLLs.
Had the same issue, sorted with the following lines
System.load("/usr/local/lib/liblept.so.5")
System.loadLibrary("tesseract")
For your case, it might be different libraries but in the end is pretty much the same: just load the libraries that you need manually.
Why don't you use JNA API http://www.java2s.com/Code/Jar/j/Downloadjna351jar.htm to load native library? Once you putted into your project classpath, you add this code
NativeLibrary.addSearchPath("libtesseract302", "your native lib path"); make sure you have this libtesseract302.dll file, normally it is located at windows32 folder.
For example, if your libtesseract302.dll file in somewhere c:/abcv/aaa/libtesseract302.dll then you just set the path like this NativeLibrary.addSearchPath("libtesseract302", "c:/abcv/aaa");
I don't know how windows path look like either c:/abcv/aaa or c:\\abcv\\aaa\\
if you want easier way, just put all your necessary dll file into your windows32 folder, JVM will take care of it.
Another issue might be you were not installing the application correctly or the application version is unmatch with your jar version. try to install the latest application and download the latest jar to try again. Hope it helps :)
I had the same problem and found that this "resource path" is not set by "native directory path" .
You can however add new folders to it by using "Add External Class Folder" in the Library tab, even if this folder does not contain any class file but native library files(like DLL on Windows)
A few days ago I ran into the same error message when trying to load a C++ DLL with JNA. It turned out that the cause was a missing DLL that my DLL depended on.
In my case it was the MS Visual Studio 2012 redistributable, which I then downloaded and installed on the machine and the problem was gone. Try using Dependency Walker to find any missing libraries and install them.
I think an easier way to get around this error would be to revert to an earlier version where you were not getting this error. Right click on the project folder and navigate to local history to revert to an earlier version. I verified this workaround on the android studio installed on Mac OS Big sur.

Categories

Resources