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

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

在此处输入图像描述

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

我已经将OpenCV jar添加为库,而Native Library链接到/ build / java / x64,如SO答案中所建议的那样。

Java构建路径

System.loadLibrary(Core.Native_Library_Name)发生exception,我检查了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); } } 

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

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

  1. .so在Linux中,
  2. Windows上的.dll
  3. Mac中的.dylib

那个库不存在

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

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


如何处理UnsatisfiedLinkError?

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

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

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

 java -Djava.library.path= "" –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 

从命令提示符运行时,您似乎需要将包含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中