Skip to content

The UnsatisfiedLinkError X File (a real experience)

jordi domenech edited this page Jun 3, 2016 · 1 revision

So, you're getting a crash at runtime with that java.lang.UnsatisfiedLinkError heading the stacktrace? And maybe that's happening in some devices but everything works like a charm in some others? Ok, we can solve that!

We also faced the same crash in our Android JavaCV based application. It worked really well in our Nexus 4, but it crashed in our Samsung S5. First of all, we need to be sure that we're adding the native libraries in the right way. For our project, our choice was the manual installation of the bunch of libraries:

  • [your app or module dir]/libs/[javacpp,javacv,opencv].jar
  • [your app or module dir]/src/main/jniLibs/[armeabi,armeabi-v7a,x86]/*.so

As you may guess, we used Android Studio (v2.1.1). We downloaded the JavaCV binaries from JavaCV Github home, copied the Java jars to the libs directory, changed the extension of opencv-android-arm.jar and opencv-android-x86.jar to .tar and after untar each file, we copied the *.so files to the corresponding armeabi and x86 arch directories. Also just make a plain copy of armeabi to armeabi-v7a.

You need to read this, it's a really good explanation of what is happening behind those java.lang.UnsatisfiedLinkError crashes, but if you want to go straight to the point, add ReLinker to your project. Now, before any use of JavaCV (or the preset of your needs), make sure you're using ReLinker in order to load the libraries, something like this:

ReLinker.Logger logger = new ReLinker.Logger() {
    @Override
    public void log(String message) {
        Log.v("HODOR", "(hold the door) " + message);
    }
};
ReLinker.log(logger).recursively().loadLibrary(context, "jniopencv_core");
ReLinker.log(logger).recursively().loadLibrary(context, "opencv_core");
ReLinker.log(logger).recursively().loadLibrary(context, "jniopencv_imgcodecs");
ReLinker.log(logger).recursively().loadLibrary(context, "opencv_imgcodecs");
ReLinker.log(logger).recursively().loadLibrary(context, "jniopencv_imgproc");
ReLinker.log(logger).recursively().loadLibrary(context, "opencv_imgproc");

In our case, we load each JavaCV library we import statically in our project, both jniopencv_* and opencv_*. Notice that we're removing the lib prefix and the .so sufix from the library file name.

And... voilà! no more crashes in our lovely Galaxy S5.