2016-04-21 14 views
5

Kod działa poprawnie podczas wykonywania z Eclipse. Używam OpenCV 2.4.11 i JavaFX dla interfejsu użytkownika. Kiedy wyeksportować plik wykonywalny słoik z Eclipse i uruchomić go z cmd pojawia się następujący wyjątek:UnsatisfiedLinkError w eksportowanym (Eclipse) pliku JAR wykonywalny

enter image description here

ja po wielu post tutaj na SO i forum OpenCV (1, 2, 3, 4), ale żaden Odpowiedzi wydają mi się pomocne.

Dodałem słoik OpenCV jako bibliotekę, a biblioteka Natywna jest połączona z/build/java/x64 zgodnie z sugestiami w odpowiedziach na SO.

Java Build path

Wyjątek występuje w System.loadLibrary (Core.Native_Library_Name) Sprawdziłem Native_Library_Name a wersja OpenCV jest taki sam jak ja importowanego w moim projekcie.

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

Jeśli ktoś myśli, że coś przegapiłem, proszę dać mi znać.

+0

Skoro już wydaje się, że znalazł swoje rozwiązanie, proponuję jeszcze spojrzeć na kopalni. Z moim nie musisz podawać żadnej bezwzględnej ścieżki, jak w innych rozwiązaniach, które oczywiście przerywają twoje wywoływanie po podaniu aplikacji innemu użytkownikowi lub po zainstalowaniu innej wersji OpenCV. – Roland

Odpowiedz

4

UnsatisfiedLinkError jest generowany, gdy aplikacja próbuje załadować natywną bibliotekę jak

  1. .so w Linuksie,
  2. .dll na Windows lub
  3. .dylib w Mac

i ta biblioteka nie istnieje.

W celu znalezienia wymaganej biblioteki natywnej JVM sprawdza zarówno właściwość systemową PATH environment variable, jak i java.library.path.

Czasami jeśli natywna biblioteka została już załadowana przez aplikację i tej samej aplikacji próbuje załadować go ponownie, może to spowodować również to błąd.


How to deal with the UnsatisfiedLinkError?

Przede wszystkim musimy sprawdzić, czy parametr przekazany w metodzie System.loadLibrary jest poprawna i że biblioteka rzeczywiście istnieje. Zauważ, że rozszerzenie biblioteki nie jest wymagane. Tak więc, jeśli biblioteka ma nazwę SampleLibrary.dll, należy przekazać wartość SampleLibrary jako parametr.

Ponadto w przypadku, gdy biblioteka jest już załadowana przez aplikację, a aplikacja próbuje ponownie ją załadować, JVM wygeneruje UnsatisfiedLinkError. Należy również sprawdzić, czy biblioteka natywna jest obecna w aplikacji java.library.path lub PATH environment library. Jeśli biblioteki nadal nie można znaleźć, spróbuj podać bezwzględną ścieżkę do metody System.loadLibrary.

Aby uruchomić aplikację, należy użyć argumentu -Djava.library.path, aby jawnie określić bibliotekę macierzystą. Na przykład za pomocą terminala (Linux lub Mac) lub wiersz polecenia (Windows), uruchom aplikację, wydając następującą komendę:

java -Djava.library.path= "<path_of_your_application>" –jar <ApplicationJAR.jar> 

Nie odebrano rzeczywisty polecenia. Użyj następujących

java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar 

lub

java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java" -jar BlurDetector.jar 

zamiast polecenia

java -Djava.library.path="C:\Users\vivek_elango\Desktop" -jar BlurDetector.jar // you have given wrong path of your application 
2

Wygląda na to, że podczas uruchamiania z wiersza polecenia trzeba dodać ścieżkę zawierającą biblioteki rodzime opencv-2411 do ścieżki -Djava.library.path.

Więc coś takiego:

java -Djava.library.path="C:\Opencv2.1.11\opencv\build\java\x64" -jar BlurDetector.jar 
1

W przeciwieństwie do innych odpowiedzi, ja raczej proponuję nie używać ścieżek bezwzględnych, zamiast korzystać z tych elementów względem siebie. Kiedy dajesz oprogramowanie innemu użytkownikowi, użytkownik z pewnością nie będzie miał bibliotek w tej samej ścieżce, co Ty. Stosując ścieżki względne w odniesieniu do aplikacji, gwarantujemy, że oprogramowanie działa również na systemach innych użytkowników, bez konieczności ustawiania zmiennych ścieżkowych, dyrektyw jvm i tego, co nie. Nie muszą nawet mieć zainstalowanego OpenCV, jeśli dasz im bibliotekę biblioteki w ten sposób.

Oto kod, aby załadować biblioteki we względnym sposób:

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

} 

Wszystko co musisz zrobić, to

  • umieścić bibliotek w lib/x64 folderu stosunku do pliku jar
  • w aplikacji należy wywołać initOpenCv() na początku programu

To wszystko. W ten sposób możesz rozwijać się jak poprzednio i utrzymywać aplikację do dystrybucji.


Oto pełna wersja:

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

Dzięki strukturze folderów jak poniżej:

.\application.jar 
.\lib\x64\*.dll 

Podpowiedź: I pakowane słoik OpenCV do aplikacji.jar

Powiązane problemy