2016-04-21 135 views
5

从Eclipse执行时,代码工作正常。我正在使用OpenCV 2.4.11和JavaFX进行用户界面。当我从Eclipse导出一个可执行的JAR和CMD我得到下面的异常运行:导出的(Eclipse)可执行文件jar文件中的UnsatisfiedLinkError

enter image description here

我跟很多张贴在这里的SO和OpenCV论坛(1234),但是,没有的答案似乎帮助我。

我已经将OpenCV jar添加为库,并且本机库链接到/ build/java/x64,如SO答案中的建议。

Java Build path

唯一的例外发生在的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

既然你似乎已经找到了你的解决方案,我建议你还是先看看我的。与我一样,您不必像在其他解决方案中那样指定任何绝对路径,一旦您将应用程序交给另一个用户或安装不同版本的OpenCV,这显然会中断您的调用。 – Roland

回答

4

UnsatisfiedLinkError当应用程序试图加载本地库像

  1. 在Linux中.so被抛出,
  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 
1

在对面的其他答案,我宁愿建议你永远不会使用绝对路径,而不是使用相对的。当您将软件交给另一个用户时,用户肯定不会将库与您在同一路径上。通过对应用程序使用相对路径,您可以保证软件也可以在其他用户系统上运行,而无需设置路径变量,jvm指令以及不需要的路径变量。他们甚至不需要安装OpenCV,如果你以这种方式给他们的图书馆的DLL。

这里的代码加载库以相对方式:

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); 
    } 

} 

所有您需要做的是

  • 把图书馆变成的lib/x64文件夹相对于你的jar文件
  • 在您的应用程序中,您必须在程序开始时调用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的水罐里的应用程序。罐子