Bruno Coelho
Bruno Coelho

Reputation: 946

Android NDK - Cannot load library: load_library on Android 17 and below

I'm using the experimental gradle plugin and this is my NDK configuration in the gradle file.

ndk {
    toolchain = "gcc"
    toolchainVersion = "4.9"
    moduleName = "libname"
    stl = "gnustl_shared"
    cppFlags.add("-std=c++11")
    cppFlags.add("-fexceptions")
    cppFlags.add("-frtti")
    ...
}

When I try to load a native library with the Android NDK with the following code

static {
    System.loadLibrary("libname");
}

It works on Android API 18 and above, but it crashed on Android API 17 and below.

I get the following error log

02-23 13:50:05.877 1937-1937/? D/dalvikvm: Late-enabling CheckJNI
02-23 13:50:05.905 1937-1944/? E/jdwp: Failed sending reply to debugger: Broken pipe
02-23 13:50:05.905 1937-1944/? D/dalvikvm: Debugger has detached; object registry had 1 entries
02-23 13:50:05.961 1937-1937/? D/dalvikvm: Trying to load lib /data/data/com.mycompany.helloworld/lib/libhelloworld.so 0xa6d15c60
02-23 13:50:05.961 1937-1937/? W/dalvikvm: Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/mycompany/helloworld/MainActivity;
02-23 13:50:05.961 1937-1937/? W/dalvikvm: Class init failed in newInstance call (Lcom/mycompany/helloworld/MainActivity;)
02-23 13:50:05.961 1937-1937/? D/AndroidRuntime: Shutting down VM
02-23 13:50:05.961 1937-1937/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa6296288)
02-23 13:50:05.969 1937-1937/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 java.lang.ExceptionInInitializerError
                                                     at java.lang.Class.newInstanceImpl(Native Method)
                                                     at java.lang.Class.newInstance(Class.java:1319)
                                                     at android.app.Instrumentation.newActivity(Instrumentation.java:1053)
                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1974)
                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
                                                     at android.app.ActivityThread.access$600(ActivityThread.java:130)
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
                                                     at android.os.Handler.dispatchMessage(Handler.java:99)
                                                     at android.os.Looper.loop(Looper.java:137)
                                                     at android.app.ActivityThread.main(ActivityThread.java:4745)
                                                     at java.lang.reflect.Method.invokeNative(Native Method)
                                                     at java.lang.reflect.Method.invoke(Method.java:511)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                     at dalvik.system.NativeStart.main(Native Method)
                                              Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: load_library[1098]: Library     '/system/lib/libhoudini.so' not found
                                                     at java.lang.Runtime.loadLibrary(Runtime.java:370)
                                                     at java.lang.System.loadLibrary(System.java:535)
                                                     at com.mycompany.helloworld.MainActivity.<clinit>(MainActivity.java:15)
                                                     at java.lang.Class.newInstanceImpl(Native Method) 
                                                     at java.lang.Class.newInstance(Class.java:1319) 
                                                     at android.app.Instrumentation.newActivity(Instrumentation.java:1053) 
                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1974) 
                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 
                                                     at android.app.ActivityThread.access$600(ActivityThread.java:130) 
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 
                                                     at android.os.Handler.dispatchMessage(Handler.java:99) 
                                                     at android.os.Looper.loop(Looper.java:137) 
                                                     at android.app.ActivityThread.main(ActivityThread.java:4745) 
                                                     at java.lang.reflect.Method.invokeNative(Native Method) 
                                                     at java.lang.reflect.Method.invoke(Method.java:511) 
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
                                                     at dalvik.system.NativeStart.main(Native Method) 
02-23 13:55:06.113 1937-1937/? I/Process: Sending signal. PID: 1937 SIG: 9

Here is a project example:

https://github.com/4brunu/djinni-hello-world

Upvotes: 4

Views: 3817

Answers (1)

Bruno Coelho
Bruno Coelho

Reputation: 946

The problem is that when using a shared library variant of the C++ runtime, it need to be loaded before the other libraries, so the solution is instead of this:

static {
    System.loadLibrary("libname");
}

Using this:

static {
    System.loadLibrary("gnustl_shared");
    System.loadLibrary("libname");         
}

Found the solution in the link bellow, in the section "Shared runtimes": http://developer.android.com/ndk/guides/cpp-support.html#ic

If your app targets a version of Android earlier than Android 4.3 (Android API level 18), and you use the shared library variant of a given C++ runtime, you must load the shared library before any other library that depends on it.

For example, an app may have the following modules:

libfoo.so

libbar.so which is used by libfoo.so

libstlport_shared.so, used by both libfoo and libbar

You must load the libraries in reverse dependency order:

static {
  System.loadLibrary("stlport_shared");
  System.loadLibrary("bar");
  System.loadLibrary("foo");
}

Here is the project example working: https://github.com/4brunu/djinni-hello-world/commit/9c1e7aadd3a593419a6004c0528e1972d24f33c9

ATENTION: there are multiple shared library variant of the C++ runtime, not only gnustl_shared. The list of the current library variant can be found in the current link: http://developer.android.com/ndk/guides/cpp-support.html#hr

Upvotes: 4

Related Questions