Tag Archives: Android difficulties

[Solved] Non-fatal Exception: java.lang.UnsatisfiedLinkError: dlopen failed: library “libmmkv.so“ not found

Project scenario:

The mmkv version 1.0.23 used in the project is too old, and 1.0.23 also introduces libc++_shared.so which is about 249K + libmmkv.so which is about 40K.

Checking github, I found that the latest version has reached 1.2.14 and the aar package has been optimized, so I have a need to upgrade.


Problem description

In the project, we upgraded mmkv version 1.0.23 to 1.2.14. After solving a lot of compilation errors (inconsistent kotlin versions, gradle upgrade required, etc.), we thought everything was all right, but we didn’t expect to report the startup

Non-fatal Exception: java.lang.UnsatisfiedLinkError: dlopen failed: library “libmmkv.so” not found

I searched various posts on the Internet – no answer. Later, someone in github issue raised similar questions: dlopen failed: library “libmmkv. so” not found · Issue # 958 · Tencent/MMKV · GitHub

Inspired, we developed the source code GitHub – Tencent/MMKV: An efficient, small mobile key value storage framework by WeChat Works on Android, iOS, macOS, Windows, and POSIX. Clone down and study.


Cause analysis:

After compiling the mmkv module with the source code clone, it is found that only the following four cpu architecture sos will be generated in the compilation log

armeabi-v7a, arm64-v8a, x86,  x86_64

No armeabi generated

My own project only supports armeabi

Therefore, the reason is obviously related to the CPU architecture settings of your project.

Why didn’t you compile so to generate armeabi?

The ndk17 does not support armeabi at first. The ndk version needs to be changed to 16 and below and the gradle plug-in needs to be downgraded to 4.1.3 and below. However, the gradle in the project has been upgraded to 7. x


Solution:

Method 1: The app’s build.gradle checks for ndk abiFilters under android-buildTypes

ndk {
    abiFilters "armeabi"
}

Modify to

ndk {
          abiFilters "armeabi-v7a"

}

Armeabi-v7a is backward compatible with armeabi

Method 2: If the project has only armeabi architecture and cannot upgrade to v7a, you can find the armeabi-v7a so through the aar package that mmkv maven depends on, put the so into the project armeabi directory, and the abiFilters can still be “armeabi”.

Could not find method causes verifyerror, which in turn causes crash

On Android 5.0 and below, sometimes the course not find method causes verifyerror, which leads to crash. The writing method is as follows:

 

As shown in the figure above, calling static method test1 on Android 4.4 mobile phone will report the following error:

  10-28 16:02:40.913 2792-2792/com.example.myapplication I/dalvikvm: Could not find method com.bumptech.glide.Glide.with, referenced from method com.example.myapplication.TestKt.test2
10-28 16:02:40.913 2792-2792/com.example.myapplication W/dalvikvm: VFY: unable to resolve static method 4: Lcom/bumptech/glide/Glide;. with (Landroid/content/Context;)Lcom/bumptech/glide/RequestManager;

The reason is that Android 5 is a delvikvm virtual machine before, and then other static methods will be loaded when the static method is invoked. So when the test1 is called, the Glide in test2 will be loaded, but at this time it will be found that the with method can not find the method, so the problem can not be found, which will lead to the explosion of VerifyError error.

Solution: Although compileonly is intentionally written above, brand differentiation may occur on mobile phones of different brands, and then some brands do not rely on relevant classes to report errors. Therefore, you can change the places in test2 that need to be called to the dynamic loading mode, that is, the reflection mode, so that test2 will be loaded when test1 is called, However, the reflection method must be called to load the class, that is, the problem of calling test1 and then failing to find the method will not occur.

Examples of solutions are as follows:

public fun test2(context:Context) {
    try {
        Log.e("Test", "test1")
        val clazz = Class.forName("com.bumptech.glide.Glide")
        val getMethod: Method = clazz.getMethod("with", context.javaClass)
        getMethod.invoke(null, context)
    } catch (e: Exception) {
        Log.e("Test","test1 e "+e.message)
    }
}

Note: the above error is OK on Android 5.0 and above phones. It should be the difference between dalvikvm and artvm