triplebig
triplebig

Reputation: 432

IntelliJ executable Jar file with OpenCV

I'm trying to use IntelliJ to export a java project that is using an external library, in this case, OpenCV. Initially, I kept getting an "Unsatisfied Link Error", even though the external libraries were already set as dependencies. I searched online and saw that I had to set the VM here:

enter image description here

So I set the library path to where I have openCV in my computer. After I did this, the program ran and compiled correctly.

My task now is to export the project into a runnable jar file, without the target computer requiring having openCV installed. I followed the advice from this post. This is how my setup Artifact looks like:

enter image description here

So after I export, and try to double click it, it does nothing. I then run it with the "java -jar .jar" which results in the good old "Unsatisfied Link Error" problem:

enter image description here

I pretty much understand what the problem is, but I have no idea how I can fix it... How do I set the VM options in the executable to point to the extracted jar file?

Upvotes: 2

Views: 1271

Answers (1)

Andrew Mackenzie
Andrew Mackenzie

Reputation: 5745

I believe that you should also include the native library files from OpenCV that are in build/lib

In my case on Mac that is libopencv_java310.dynlib

Screenshot of artifact description

In my screenshot you can see the OpenCV java library (.jar), plus my module's compiled output, plus I have included both versions of the shared library (.dynlib for Mac, and .so for Linux).

If you are on Windows then I guess your OpenCV build/install will give you a .dll that you should also include.

If you want the shared library file to be found from your file system when you are running/developing, but want a clean distribution of it and it to be found in the JAR file when others run it, then you might want to load it with code like this instead that handles both cases:

import cz.adamh.utils.NativeUtils;

class SimpleSample {
  static {
    try {
      System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    } catch (UnsatisfiedLinkError e) {
      try {
        NativeUtils.loadLibraryFromJar("/" + System.mapLibraryName(Core.NATIVE_LIBRARY_NAME));
      } catch (IOException e1) {
        throw new RuntimeException(e1);
      }
    }
  }

You can find that utility class of cz.adamh.utils.NativeUtils on his GitHub here https://github.com/adamheinrich/native-utils/blob/master/src/main/java/cz/adamh/utils/NativeUtils.java

The path to the file in the JAR must begin with "/". I have my native libraries in the root of the JAR in my example, so "/" is pre-pended. If you put your native extensions in a sub-folder in the JAR then specify the path to it in the code above.

Then on the different platforms I believe the JVM will find the "right" shared native library to use when you try and load it at runtime.

I have done that with the SimpleSample (in samples/java/ant).

Then I generate the JAR using IntelliJ menu "Build > Built Artifacts".

Then I can run it using:

java -jar ../opencv-java-sample/out/artifacts/SimpleSample_jar/SimpleSample.jar

Upvotes: 1

Related Questions