java.lang.UnsatisfiedLinkError: dlopen failed: library "../../../../libs/arm64-v8a/libhello.so

3,139 views
Skip to first unread message

minjun...@gmail.com

unread,
Jul 5, 2017, 10:02:13 AM7/5/17
to android-ndk
Hi all,

I am trying to import the prebuilt native libraries to the Android app with ndk support.

With editing the build.gradle file for the app module, and editing the CMakeLists.txt file, the apk files can be built successfully. 
There're two libraries in the apk file, like this:

lib
  |_arm64-v8a
           |___libnative-lib.so
           |___libhello.so

However, when I am running this app, there will be one FATAL exception. From the log, I got the UnsatisfiedLinkError.

I am very curious that the libraries are located in the `lib` directory of the apk file, why does `dlopen` treat `libs/<arch>/` as the default search path? 

Thanks.

Best regards,
Minjun

minjun...@gmail.com

unread,
Jul 6, 2017, 9:55:34 AM7/6/17
to android-ndk
Updates:

I checked the installed path on the device, and I found the files are installed to the "lib/arm64/" directory. I tried to duplicate the directory to "libs/arm64-v8a", but it doesn't work.

Why does "dlopen" try to open "../../../../libs/arm64-v8a/libhello.so", but there's no such directory in the app, is it hard-coded?

Thanks.

Andrew Esh

unread,
Jul 7, 2017, 10:03:56 AM7/7/17
to android-ndk
Why not just open the directory where the library actually is? Figure out where the library is being installed by the packaging, and load it from there.

Also, in Android O, there is another path component added to the library path which is an un-guessable hash. The hash is changed every time
the app is installed, so you can't use a hardcoded path to dlopen the library any more. To support this, I added a reverse JNI call from C to Java
to call "[context].getContext().getApplicationInfo().nativeLibraryDir;". If you were to do this, it would solve your immediate problem, and it will
solve the Android O porting problem in the future.

Alex Cohn

unread,
Jul 7, 2017, 10:57:47 AM7/7/17
to android-ndk
How do you load libhello.so in your app? Maybe it depends on other libraries, that are not installed?

BR,
Alex

minjun...@gmail.com

unread,
Jul 10, 2017, 10:28:14 AM7/10/17
to android-ndk
The libhello.so is only one dumb library with one simple function (returning one int value). 

I think I might have found the reason, but not sure.

The libhello.so is prebuilt with aarch64-linux-android- cross compiler, but android studio seems using clang to compile native code.  Do you know if there are any special instructions to prebuilt the libraries without android-studio? The libhello.so library works with the native CLI binary under Android shell, but it might not work well with the clang-compiled Android apps.

The error message might be misleading, when it says  "dlopen() failed with blah/blah/blah/xxx.so". The path ("../../../../libs/arm64-v8a/libhello.so") should be updated to the actual path in the device accordingly, but it is not updated, I don't know which part should be responsible to it....

Alex Cohn

unread,
Jul 10, 2017, 3:29:54 PM7/10/17
to android-ndk
There could be a problem with your toolchain. But with the linker, rather than the compiler. If you set rpath for libhello.so, it's no good.

BR,
Alex

minjun...@gmail.com

unread,
Jul 14, 2017, 12:56:54 AM7/14/17
to android-ndk
Thanks for your help. :D

I digged into all the options used by the ninja and cmake building system in Android studio NDK support, and finally got the key linker options:

-Wl,-soname,libhello.so

This is important, and the file name (libhello.so) has to be the same with the final library file put into the ndk project.

Alex Cohn

unread,
Jul 15, 2017, 9:11:33 AM7/15/17
to android-ndk
No, soname cannot be a problem. Also, we are not suspecting the part that builds libhello.so, but rather the part that is dependent on it.

BR,
Alex

Alex Cohn

unread,
Jul 18, 2017, 2:58:28 PM7/18/17
to android-ndk
Note that there was a change for API 23 that may manifest itself in described behavior: https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#Correct-soname_path-handling-Available-in-API-level-23

This still does not explain what in your toolchain could have triggered the problem.

BR,
Alex

On Friday, July 14, 2017 at 7:56:54 AM UTC+3, minjun...@gmail.com wrote:

Sonaali

unread,
Aug 28, 2018, 1:27:23 PM8/28/18
to android-ndk
Hi, i am facing a similar issue with my application. just wanted to ask @minjun, how you finally solved it?? 
by adding the linker flags only, was it??
Thanks and regards,

S.G. Vogel

unread,
Aug 31, 2018, 4:54:10 PM8/31/18
to android-ndk
Hi
You have a lot of good NDK answers on SO.
Can you answer this:

Hans' 2017 talk at googleio about managing native memory does not touch on global reference use but shows that JNI can be wonky.

https://developer.android.com/training/articles/perf-jni says:

The global reference is guaranteed to be valid until you call DeleteGlobalRef.

Do you have any experience in Android when this does not hold true?

Reply all
Reply to author
Forward
0 new messages