导出 (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
.so
在 Linux、
.dll
在 Windows 或
.dylib
在 Mac
并且该库不存在。
具体来说,为了找到所需的本机库,JVM 在 PATH environment variable
和 java.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.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
从 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
.so
在 Linux、.dll
在 Windows 或.dylib
在 Mac
并且该库不存在。
具体来说,为了找到所需的本机库,JVM 在 PATH environment variable
和 java.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.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