0

I can not seem to able to build my project properly, I have tired many things however none of them worked.

The project works fine in the IDE, but its not working once I build the project into a jar file.

Here's the code for the main class

@Override
public void start(Stage primaryStage) throws Exception{


    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//The issue appears to be (line 24)here

    FXMLLoader loader = new FXMLLoader(getClass().getResource("ScreenDesign.fxml"));
    Controller controller = loader.getController();

    //This finds the scene predefined with scene builder
    Parent root = loader.load(getClass().getResource("ScreenDesign.fxml"));

}

This is what I get when I run the jar file:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.UnsatisfiedLinkError: no opencv_java345 in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at com.abdrnasr.hl.Main.start(Main.java:24)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    ... 1 more
Exception running application com.abdrnasr.hl.Main

Here is the structure of the output jar using a decompiler: enter image description here

EDIT: This the error that i get when i run the code without System.load() line.

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.UnsatisfiedLinkError: org.opencv.videoio.VideoCapture.VideoCapture_4()J
    at org.opencv.videoio.VideoCapture.VideoCapture_4(Native Method)
    at org.opencv.videoio.VideoCapture.<init>(VideoCapture.java:86)
    at com.abdrnasr.hl.Controller.<init>(Controller.java:28)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:927)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at com.abdrnasr.hl.Main.start(Main.java:28)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    ... 1 more
Exception running application com.abdrnasr.hl.Main
A NASR
  • 3
  • 5

1 Answers1

1

It is not possible to load a native library directly from an executable .jar file. This is because methods like System.loadLibrary look for a physical library file. Even if your native libraries were inside your jar, they would not be separate files and the operating system would not be able to load them.

If you are using Java 9 or later, and if you are willing to make your application use Java modules, you have the option of bundling the native libraries into a jmod file, since the jmod format can contain both classes and native libraries (among other things). You would then use the jlink command to create an executable image. See How to deploy a JavaFX 11 Desktop application with a JRE for more details.

If you don’t want to bother turning your application into a Java module, you can try bundling the native library in your jar file, then at runtime, copying it to a separate physical file:

String libraryEntry;
String os = System.getProperty("os.name");
if (os.contains("Windows")) {
    libraryEntry = Core.NATIVE_LIBRARY_NAME + ".dll";
} else if (os.contains("Mac")) {
    libraryEntry = "lib" + Core.NATIVE_LIBRARY_NAME + ".dylib";
} else {
    libraryEntry = "lib" + Core.NATIVE_LIBRARY_NAME + ".so";
}

Path libraryDir = Files.createTempDirectory("nativelib");
Path libraryFile = libraryDir.resolve(libraryEntry);

try (InputStream libraryResource =
    Main.class.getResourceAsStream("/" + libraryEntry)) {

    Files.copy(libraryResource, libraryFile);
}

System.load(libraryFile);

The above code assumes you have .dll, .so, and .dylib files bundled into the root of your jar. In your case, you would need opencv_java345.dll, libopencv_java345.so, and libopencv_java345.dylib to be in the jar.

I haven’t actually tried copying a native library and loading it in that manner. I have, however, successfully embedded native libraries in jmod files and jlink’d them.

VGR
  • 40,506
  • 4
  • 48
  • 63