Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caused by: java.lang.UnsatisfiedLinkError: Cannot load library

Tags:

android

I am writing a game, and I have huge native library, I am trying to load my native library in my main activity like

 static {
        try {
            System.loadLibrary("mylib");
        } catch (UnsatisfiedLinkError e) {
            Log.d(TAG, "Unsatisfied Link error: " + e.toString());
        }
    }

I have tested this code on many devices in house, I don't get this error. but from my published I do get logs with "Caused by: java.lang.UnsatisfiedLinkError: Cannot load library". NOTE: This crash is not universal, only few people are getting this crash

  • Is it problem where the library is put in exported apk ? I have now library put into /libs/armabi/libmylib.so automatically by eclipse?
  • Is it some thing to do with version of android ? I am supporting android versions since 2.3 (API level 9)
  • or do I need to load library from different place?
  • or am I missing something very important
  • Is it problem with whole app being installed on SDCARD ?

More Info on crash is : load_segments: 68 failed to map segment from mylib.so

like image 343
Shri Avatar asked May 13 '13 09:05

Shri


1 Answers

Considering that your app works correctly on most of the devices and only sometimes gives you the error, it's safe to assume that the library is packaged correctly in the APK and that its size/memory footprint is also acceptable.

As such, I'll go on the whim and suggest that the problem is with the build/compile architecture of the library. Most newer Android devices use ARM7 processor. It's quite likely that your library is compiled against ARM7 architecture as well. Some older devices, especially those running Android 2.3, use ARM6 processor (I have one such device that I use for testing - LG GT540 running Android 2.3.3), which is not forward-compatible with ARM7 architecture. I have seen a crash with error similar to the one you indicated (load_segments: 68 failed to map segment from mylib.so) when I attempted to run an app designed for ARM7 on my old ARM6 phone.

There are three ways of going around this issue:

  1. Compile the library against both architectures and include two separate .so files into the apk. Then at runtime determine the type of processor and load the correct one. Frankly, I don't know if this is even possible.

  2. Create two separate apk files - one for ARM6 and one for ARM7 - then use filters in the manifest to specify the corresponding architecture. You can upload both of them to google play for the same app - and filters in the manifest will control which one is downloaded to which device.

  3. Only support ARM7 architecture by specifying device requirements in your manifest. You will loose some customer audience, but will have less work for yourself maintaining the two versions of the app.

EDIT: According to NDK documentation, it can produce multiple libraries for different architectures in one go. You can control specifically which CPUs you want to target by adding the following line into the Application.mk file:

APP_ABI := arch1 arch2 arch3 ...

for example,

APP_ABI := armeabi armeabi-v7a mips

Then the build process will create different versions of the native library. These versions will need to be placed in the final apk in directory

lib/<abi>/lib<name>.so

where is the name of the architecture. You will then load the library with

System.loadLibrary("<name>");

Alternatively you can build separate apk files for each architecture then use multi-apk functionality on google play.

You can find all the information on architecture targeting in file CPU-ARCH-ABIS.html file in the docs subdirectory of the NDK.

like image 168
Aleks G Avatar answered Sep 18 '22 14:09

Aleks G