导出的 (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 variable
和java.library.path
系统属性。
有时如果应用程序已经加载了原生库 并且同一个应用程序尝试再次加载它,这可能会导致 也出错了。
How to deal with the UnsatisfiedLinkError?
首先我们要验证System.loadLibrary
方法中传入的参数是否正确,并且该库确实存在。请注意,不需要扩展库。因此,如果您的库名为 SampleLibrary.dll
,则必须将 SampleLibrary 值作为参数传递。
此外,如果您的应用程序已经加载了该库并且应用程序尝试再次加载它,则 JVM 将抛出 UnsatisfiedLinkError
。此外,您必须验证本机库是否存在于应用程序的java.library.path
或PATH 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的主要内容,如果未能解决你的问题,请参考以下文章