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

UnsatisfiedLinkError in exported (Eclipse) executable jar file

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

我在 SO 和 OpenCV 论坛 (1, 2, 3, 4) 上关注了很多 post 但是,none 的答案似乎对我有帮助。

我已将 OpenCV jar 添加为库,并且按照 SO 答案中的建议将本机库链接到 /build/java/x64。

异常出现在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);
    }
}

如果有人认为我遗漏了什么,请告诉我。

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

所以像这样:

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

与其他答案相反,我建议您永远不要使用绝对路径,而是使用相对路径。当您将您的软件提供给另一个用户时,该用户肯定不会在与您相同的路径中拥有这些库。通过使用与您的应用程序相关的相对路径,您可以保证该软件也可以在其他用户系统上运行,而无需他们设置路径变量、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

当应用程序尝试加载本机库时抛出 UnsatisfiedLinkError

  1. .so 在 Linux、
  2. .dll 在 Windows 或
  3. .dylib 在 Mac

并且该库不存在

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

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?

首先要验证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