Search code examples
javamatlabjava-native-interfaceunsatisfiedlinkerror

Matlab + Java + JNI: java.lang.UnsatisfiedLinkError


Using Matlab with Java and JNI, I'm getting an UnsatisfiedLinkError that I cannot fathom.

First I load a native library from the Matlab command line. It works:

>> java.lang.System.load('/usr/local/share/OpenCV/java/libopencv_java.so')

Then I call a Java function implemented with the native library:

>> org.opencv.core.Mat

   Java exception occurred:
   java.lang.UnsatisfiedLinkError: org.opencv.core.Mat.n_Mat()J
    at org.opencv.core.Mat.n_Mat(Native Method)
    at org.opencv.core.Mat.<init>(Mat.java:441)

It's complaining it can't find org.opencv.core.Mat.n_Mat()J, but that symbol is in the .so:

echristiansen@jnu:/usr/local/share/OpenCV/java$ nm libopencv_java.so | grep Mat_n_1Mat
0000000000027780 T Java_org_opencv_core_Mat_n_1Mat__
00000000000316c0 T Java_org_opencv_core_Mat_n_1Mat__DDI
00000000000312a0 T Java_org_opencv_core_Mat_n_1Mat__DDIDDDD
00000000000318a0 T Java_org_opencv_core_Mat_n_1Mat__III
00000000000314b0 T Java_org_opencv_core_Mat_n_1Mat__IIIDDDD
0000000000030fa0 T Java_org_opencv_core_Mat_n_1Mat__JII
0000000000031120 T Java_org_opencv_core_Mat_n_1Mat__JIIII

So if it's loading the native library with the correct symbol, why am I getting an UnsatisifiedLinkError?


Solution

  • The issue seems to be that the call to System.load happens in the Matlab REPL, not in a pre-built jar. The workaround: 1) Write a simple class that just loads the native library, 2) Build the class and add it to the Matlab Java class path, 3) To load the native library, call the simple function you just wrote.

    My simple class looks like this:

    public class LoadOpenCV {
        public static void loadOpenCV() {
            System.load("/usr/local/share/OpenCV/java/libopencv_java.so");
        }
    }
    

    The Matlab call looks like this:

    >> LoadOpenCV.loadOpenCV
    >> org.opencv.core.Mat
    
    ans =
    
    Mat [ 0*0*CV_8UC1, isCont=false, isSubmat=false, nativeObj=0x7f174286d800, dataAddr=0x0 ]
    

    Now to figure out why this works; clearly something in the difference between the REPL and compiled code.