The code works fine when executing from Eclipse. I'm using OpenCV 2.4.11 and JavaFX for UI. When I export an Executable Jar from Eclipse and run it from cmd I get the following exception:
I followed many post here on SO and OpenCV forum(1, 2, 3, 4) but, none of the answers seems to help me.
I have added the OpenCV jar as library and Native Library is linked to /build/java/x64 as suggested in SO answers.
The exception occurs at the System.loadLibrary(Core.Native_Library_Name), I checked the Native_Library_Name and the OpenCV version is same as the one I imported in my project.
public class CustomFrame extends Application{
@Override
public void start(Stage primaryStage){
Group root = new Group();
Canvas canvas = new Canvas(1440, 840);
ImageView imageView = new ImageView();
imageView.setFitHeight(canvas.getHeight());
imageView.setFitWidth(canvas.getWidth());
new FrameController().startCamera(imageView);
root.getChildren().addAll(imageView, canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args)
{
// load the native OpenCV library
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
launch(args);
}
}
If anybody thinks that I have missed something please do let me know.
The UnsatisfiedLinkError
is thrown when an application attempts to load a native library like
.so
in Linux, .dll
on Windows or .dylib
in Mac and that library does not exist.
Specifically, in order to find the required native library, the JVM looks in both the PATH environment variable
and the java.library.path
system property.
Sometimes if the native library was already loaded by an application and the same application tries to load it again, this can cause this error also.
How to deal with the UnsatisfiedLinkError?
First of all we must verify that the parameter passed in the System.loadLibrary
method is correct and that the library actually exists. Notice that the extension of the library is not required. Thus, if your library is named SampleLibrary.dll
, you must pass the SampleLibrary value as a parameter.
Moreover, in case the library is already loaded by your application and the application tries to load it again, the UnsatisfiedLinkError
will be thrown by the JVM. Also, you must verify that the native library is present either in the java.library.path
or in the PATH environment library
of your application. If the library still cannot be found, try to provide an absolute path to the System.loadLibrary method.
In order to execute your application, use the -Djava.library.path
argument, to explicitly specify the native library. For example, using the terminal (Linux or Mac) or the command prompt (Windows), execute your application by issuing the following command:
java -Djava.library.path= "<path_of_your_application>" –jar <ApplicationJAR.jar>
You have missed the actual command. Use the following
java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar
or
java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java" -jar BlurDetector.jar
instead of your command
java -Djava.library.path="C:\Users\vivek_elango\Desktop" -jar BlurDetector.jar // you have given wrong path of your application
It looks like you need to add the path containing the opencv-2411
native libraries to the -Djava.library.path
when running from the command prompt.
So something like this:
java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar
In opposite to the other answers, I rather suggest you never use absolute paths, instead use relative ones. When you give your software to another user, the user most certainly won't have the libraries in the same path as you do. By using relative paths in regards to your application you guarantee that the software runs on other users systems as well, without them having to set path variables, jvm directives and what not. They don't even have to have OpenCV installed if you give them the library dll this way.
Here's code to load the libraries in a relative way:
public static void initOpenCv() {
setLibraryPath();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.out.println("OpenCV loaded. Version: " + Core.VERSION);
}
private static void setLibraryPath() {
try {
System.setProperty("java.library.path", "lib/x64");
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
All you have to do is to
initOpenCv()
at the start of your programThat's it. This way you can develop as before and maintain a distributable application.
Here's the full version:
import java.lang.reflect.Field;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import org.opencv.core.Core;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
initOpenCv();
HBox root = new HBox();
Label infoLabel = new Label();
infoLabel.setText("OpenCV loaded. Version: " + Core.VERSION);
root.getChildren().add(infoLabel);
Scene scene = new Scene(root, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void initOpenCv() {
setLibraryPath();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
System.out.println("OpenCV loaded. Version: " + Core.VERSION);
}
private static void setLibraryPath() {
try {
System.setProperty("java.library.path", "lib/x64");
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
public static void main(String[] args) {
launch(args);
}
}
With a folder structure like this:
.\application.jar
.\lib\x64\*.dll
Hint: I packaged the opencv jar into the application.jar
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With