从Eclipse执行代码时,代码工作正常。我正在使用OpenCV 2.4.11和JavaFX for UI。当我从Eclipse导出可执行jar并从cmd运行它时,我得到以下异常:
我在SO和OpenCV论坛(1,2,3,4上发布了很多帖子,但是,这些答案似乎都没有帮助我。< / p>
我已将OpenCV jar添加为库,而Native库链接到/ 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);
}
}
如果有人认为我错过了什么,请告诉我。
答案 0 :(得分:7)
当应用程序尝试加载本机库(如
)时,会引发UnsatisfiedLinkError
.so
,.dll
或.dylib
和该库不存在。
具体来说,为了找到所需的本机库,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
答案 1 :(得分:2)
从命令提示符运行时,您似乎需要将包含opencv-2411
本机库的路径添加到-Djava.library.path
。
这样的事情:
java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar
答案 2 :(得分:2)
与其他答案相反,我建议你永远不要使用绝对路径,而是使用相对路径。当您将软件提供给其他用户时,用户肯定不会拥有与您相同路径的库。通过使用与应用程序相关的相对路径,您可以保证软件也可以在其他用户系统上运行,而无需设置路径变量,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);
}
}
您所要做的就是
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
中