3

I am loading my native library by:

try {
       System.loadLibrary("myNative");
} catch (UnsatisfiedLinkError e) {
       //java.lang.UnsatisfiedLinkError here
       System.load("/data/data/com.my.app/app_native/libmyNative.so");
}

The above code is finally packaged to a Jar file.

In another project, I load the above Jar with DexClassLoader:

DexClassLoader dexClassLoader = new DexClassLoader(jarPath,
                    optJarPath,
                    getDir("native", Context.MODE_PRIVATE),
                    getClassLoader());

Notice that when constructing this dexClassLoader instance, I have specified the path where the native code is located, that's getDir("native", Context.MODE_PRIVATE).

(I am using NDK release 10 to generate the native library. When the native code file libmyNative.so is generated, my java code (which packaged to final Jar) checks the CPU architecture type & copy the right one to getDir("native", Context.MODE_PRIVATE).)

The above code works fine on other devices except Android 5.0 Lollipop. When run on Android 5.0 Lollipop device, I constantly get the following error:

java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.my.app/app_native/libmyNative.so" is 32-bit instead of 64-bit
at java.lang.Runtime.load(Runtime.java:331)
at java.lang.System.load(System.java:982)

How to solve this problem?

Leem.fin
  • 40,781
  • 83
  • 202
  • 354
  • You appear to be attempting to use a 32-bit library on a 64-bit target. If you can't provide a 64-bit one, you will have to convince Android to fallback to 32-bit mode to accommodate the library. http://stackoverflow.com/questions/27712921/how-to-use-32bit-native-libraries-on-64-bit-android-l-platform Suggests that this occurs if the installer detects only 32-bit libraries in the APK. If you can't find another way to trigger that mode, you might need to include a placeholder 32-bit library in the actual APK for the installer to see and respond to. Ultimately, can you provide a 64-bit lib? – Chris Stratton Mar 27 '15 at 12:11
  • @ChrisStratton, thanks for your comment, I need to run my 32-bit lib on 64-bit target, this is the goal I want to achieve now. – Leem.fin Mar 27 '15 at 13:08
  • 1
    Then I'd suggest you try putting a dummy 32-bit lib in the apk. – Chris Stratton Mar 27 '15 at 14:29
  • @ChrisStratton, 1. why I need this dummy 32-bit lib if I want the system to load my real 32-bit lib? I don't get it. 2. How could I create a dummy 32-lib ?? – Leem.fin Mar 29 '15 at 10:59
  • You have already asked this question at http://stackoverflow.com/questions/28992323/unsatisfiedlinkerror-on-android-5-0-lollipop Re-posting is not permitted. – Chris Stratton Mar 29 '15 at 16:43

1 Answers1

1

You appear to be attempting to use a 32-bit library on a 64-bit target. If you can't provide a 64-bit one, you will have to convince Android to fallback to 32-bit mode to accommodate the library.

Apparently, compatibility mode (the source seems to call it an ABI override) is normally set at install time, by the installer discovering that only 32-bit (and not 64-bit) libraries are available. But in your case, the library is not visible at install time, so that won't work.

If you place a "dummy" 32-bit lib in the apk that is the closest match for the 64-bit device's needs, then the system will hopefully configure your app to run in 32-bit compatibility mode so that later loading your real 32-bit lib will actually work.

I don't know if the 32-bit lib would need to be a real one vs. an empty file with the correct location and plausible name, but the hello-jni project from the ndk samples folder's libhello-jni.so should should work. You won't need any corresponding java code, just to have a native library the installer can discover (however, calling into it as a test might not be a bad idea).

It is possible there may be some other way(s) to trigger this, such as something in the manifest (though nothing is mentioned in the documentation). I'd be less likely to suspect that any measures at runtime will work, since this mode may already be firmly set before any of your code runs (it looks like you may actually end up with two instances of zygote running on such a system, one 64 bit and the other 32, with the idea being that apps get launched by whichever one is believed to be appropriate).

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
  • 1. `in your case, the library is not visible at install time` why?? 2. What is the the path of the dummy 32-bit libt inside APK? /libs/libmyNative.so ?? – Leem.fin Mar 29 '15 at 15:36
  • 1
    If the *real* library is present in the apk, then you are going about this in entirely the wrong way - you should not be copying the native lib yourself, but rather letting the system automatically copy it out of the apk and automatically find the result when you call System.loadLibrary(). On the other hand, if the real library is *not* in the apk after all (presumably because you plan to download it later), then put the dummy library in the traditional directory for its ABI - ie, follow the NDK instructions *exactly*. – Chris Stratton Mar 29 '15 at 15:39
  • As of today, using Android 2.1 with latest experimental gradle, using a compileSdkVersion lower or equal to 19 prevents building the 64 bits shared library, and 32 bits shared library are not installed on 64 bits Android. It's a mess because it's not possible to build a single APK to support API above and below 19 at the same time, even though shared library works just fine on all API version, except that shared library compiled with 20/21+ will not work on API 19 and below at all because of changed C libraries. A mess. – 3c71 May 19 '16 at 18:24
  • @3c71 - it's unclear what you are talking about (Android 2.1? really?) but at any rate this is the wrong place for it - this question was closed as a duplicate, ie, this page is not really supposed to exist. – Chris Stratton May 19 '16 at 23:45
  • LOL, indeed, I meant Android Studio 2.1. to get 64 bits libraries, I had to make 2 modules, both pointing to the same src folder, one with compileSdkVersion 19, one with compileSdkVersion 21. The first would build non-64 bits libraries compatible with API19 and lower, while the second would build 64 bits libraries compatible with API20 and above. Yeah, didn't see it was closed. – 3c71 May 22 '16 at 05:33