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

Posted

技术标签:

【中文标题】导出的 (Eclipse) 可执行 jar 文件中的 UnsatisfiedLinkError【英文标题】:UnsatisfiedLinkError in exported (Eclipse) executable jar file 【发布时间】:2016-08-15 06:28:15 【问题描述】:

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

我在 SO 和 OpenCV 论坛上关注了很多帖子(1、2、3、4)但是,似乎没有一个答案对我有帮助。

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

异常发生在 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,这显然会破坏您的调用。 【参考方案1】:

UnsatisfiedLinkError 在应用程序尝试加载原生库时抛出

    .so 在 Linux 中, .dll 在 Windows 上或 .dylib 在 Mac 中

并且该库不存在

具体来说,为了找到所需的本机库,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

【讨论】:

【参考方案2】:

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

所以是这样的:

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

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于导出的 (Eclipse) 可执行 jar 文件中的 UnsatisfiedLinkError的主要内容,如果未能解决你的问题,请参考以下文章

eclipse怎么导出可执行jar包

eclipse导出可执行jar包步骤

eclipse导出可执行jar包步骤

eclipse 导出java 可执行jar

eclipse 导出java 可执行jar

eclipse 导出java 可执行jar