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

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

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

我已将 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,这显然会破坏您的调用。

标签: java eclipse opencv javafx executable-jar


【解决方案1】:

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

  1. .so 在 Linux 中,
  2. .dll 在 Windows 上或
  3. .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中

      【讨论】:

        猜你喜欢
        • 2014-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-16
        • 2014-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多