导出的(Eclipse)可执行jar文件中的UnsatisfiedLinkError

时间:2016-04-21 20:40:05

标签: java eclipse opencv javafx executable-jar

从Eclipse执行代码时,代码工作正常。我正在使用OpenCV 2.4.11和JavaFX for UI。当我从Eclipse导出可执行jar并从cmd运行它时,我得到以下异常:

enter image description here

我在SO和OpenCV论坛(1234上发布了很多帖子,但是,这些答案似乎都没有帮助我。< / p>

我已将OpenCV jar添加为库,而Native库链接到/ build / java / x64,如SO答案所示。

Java Build path

异常发生在System.loadLibrary(Core.Native_Library_Name),我检查了Native_Library_Name,OpenCV版本与我在项目中导入的版本相同。

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);
    }
}

如果有人认为我错过了什么,请告诉我。

3 个答案:

答案 0 :(得分:7)

当应用程序尝试加载本机库(如

)时,会引发UnsatisfiedLinkError
    Linux中的
  1. .so
  2. Windows上的
  3. .dll
  4. Mac中的
  5. .dylib
  6. 该库不存在

    具体来说,为了找到所需的本机库,JVM同时查找PATH environment variablejava.library.path系统属性。

      

    有时,如果应用程序已加载本机库   并且同一个应用程序尝试再次加载它,这可能会导致这种情况   错误也。

    How to deal with the UnsatisfiedLinkError?

    首先,我们必须验证System.loadLibrary方法中传递的参数是否正确以及库实际存在。请注意,不需要扩展库。因此,如果您的库名为SampleLibrary.dll,则必须将SampleLibrary值作为参数传递。

    此外,如果您的应用程序已加载库并且应用程序尝试再次加载它,则JVM将抛出UnsatisfiedLinkError。此外,您必须验证应用程序的java.library.pathPATH environment library中是否存在本机库。 如果仍然找不到库,请尝试提供System.loadLibrary方法的绝对路径。

    为了执行您的应用程序,请使用-Djava.library.path参数来显式指定本机库。例如,使用终端(Linux或Mac)或命令提示符(Windows),通过发出以下命令来执行您的应用程序:

    java -Djava.library.path= "<path_of_your_application>" –jar <ApplicationJAR.jar>
    

    你错过了实际的命令。使用以下

    java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar
    

    java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java" -jar BlurDetector.jar
    

    而不是你的命令

    java -Djava.library.path="C:\Users\vivek_elango\Desktop" -jar BlurDetector.jar // you have given wrong path of your application
    

答案 1 :(得分:2)

从命令提示符运行时,您似乎需要将包含opencv-2411本机库的路径添加到-Djava.library.path

这样的事情:

java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar

答案 2 :(得分:2)

与其他答案相反,我建议你永远不要使用绝对路径,而是使用相对路径。当您将软件提供给其他用户时,用户肯定不会拥有与您相同路径的库。通过使用与应用程序相关的相对路径,您可以保证软件也可以在其他用户系统上运行,而无需设置路径变量,jvm指令等等。如果你以这种方式给他们库dll,他们甚至不必安装OpenCV。

以下是以相对方式加载库的代码:

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);
    }

}

您所要做的就是

  • 将库放入相对于jar文件的lib / x64文件夹
  • 在您的应用程序中,您必须在程序开始时调用initOpenCv()

就是这样。这样您就可以像以前一样开发并维护可分发的应用程序。

以下是完整版:

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);
    }
}

使用如下文件夹结构:

.\application.jar
.\lib\x64\*.dll

提示:我将opencv jar打包到application.jar