簡體   English   中英

導出的(Eclipse)可執行jar文件中的UnsatisfiedLinkError

[英]UnsatisfiedLinkError in exported (Eclipse) executable jar file

從Eclipse執行時,代碼工作正常。 我正在使用OpenCV 2.4.11和JavaFX for UI。 當我從Eclipse導出可執行Jar並從cmd運行它時,我得到以下異常:

在此輸入圖像描述

我跟很多張貼在這里的SO和OpenCV論壇( 1234 ),但是,沒有一個答案似乎幫助我。

我已經將OpenCV jar添加為庫,而Native Library鏈接到/ build / java / x64,如SO答案中所建議的那樣。

Java構建路徑

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

如果有人認為我錯過了什么,請告訴我。

當應用程序嘗試加載本機庫時,拋出UnsatisfiedLinkError

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

那個庫不存在

具體來說,為了找到所需的本機庫,JVM同時查找PATH environment variablejava.library.path系統屬性。

有時,如果應用程序已加載本機庫,並且同一應用程序嘗試再次加載它,則也可能導致此錯誤。


如何處理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

從命令提示符運行時,您似乎需要將包含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中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM