当前位置:   article > 正文

一文解决java.lang.UnsatisfiedLinkError

java.lang.unsatisfiedlinkerror

首先大家先了解下:

ABI和CPU

不同的 Android 手机使用不同的 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口,即 ABI。
每个 ABI 支持一个或多个指令集,每个 ABI 支持的指令集如下图。

ABI支持的指令集备注
armeabiARMV5TE 和更高版本Thumb-1在 r16 中已弃用。在 r17 中已移除。无硬浮点数。
armeabi-v7aarmeabiThumb-2VFPv3-D16其他(可选)与 ARMv5、ARMv6 设备不兼容
arm64-v8aAArch64兼容armeabi-v7a
x86x86 (IA-32)MMXSSE/2/3SSSE3不支持 MOVBE 或 SSE4。
x86_64x86-64MMXSSE/2/3SSSE3SSE4.1、4.2POPCNT

64 位设备也支持其 32 位变体。以 arm64-v8a 设备为例,该设备也可以运行 armeabi 和 armeabi-v7a 代码,但相对来说代码运行的效率也会略有降低。但请注意,如果应用以 arm64-v8a 为目标,而非依赖于运行 armeabi-v7a 版应用的设备,应用在 64 位设备上的性能要好得多。

报错原因

正常情况下,找到所需的库时,软件包管理器会将它们复制到应用的 data 目录 (data/data/<package_name>/lib/) 下的 /lib/lib.so。
如果根本没有共享对象文件,应用也会编译并安装,但在运行时会崩溃。

举个荔枝:如果你有两个文件夹armeabi和arm64-v8a。armeabi里面有a.so 和 b.so,arm64-v8a里面只有a.so,那么arm64-v8a的手机在用到b的时候发现有arm64-v8a的文件夹,但是里面没有b.so,就报错了,所以删掉arm64-v8a文件夹,这个时候手机发现没有适配arm64-v8a,就会直接去找armeabi的so库,所以要么你别加arm64-v8a,要么armeabi里面有的so库,arm64-v8a里面也必须有。

解决问题

既然已经知道了问题原因,那么咱们就单刀直入 直捣黄龙。

依旧以 arm64-v8a 设备为例,只留下armeabi-v7a文件夹(留下哪些文件夹应该根据提供的so库决定,如果有其他类型的so文件夹也可以不删除),其余的文件夹删除,并保持这两个文件夹里的文件是一样的。
然后在gradle.properties中添加:
android.useDeprecatedNdk=true
在build.gradle(app)中添加对应的cpu的.so库:

android {
   ...
    defaultConfig {
       .....
        ndk {
            //选择要添加的对应cpu类型的.so库。
//            abiFilters 'armeabi','arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
            abiFilters 'armeabi-v7a'
            moduleName "app"
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

需要注意的是:可能有些时候为了打包方便,在打包时生成多个ABI的apk,但于此是大忌!因为通过此方法打包的apk lins下只会有一个对应ABI的文件夹。
举个荔枝,若include‘arm64-v8a’,那么打出的apk中lins里只会有一个名为arm64-v8a的空文件夹 ,因为我们的so文件只存在于’armeabi-v7a’中,那么在程序运行后就会报没有so文件的错误。所以在打包多个ABI类型的apk时,一定要于添加的cpu类型的so对应。

android {
   ...
    defaultConfig {
       .....
    }
    splits {
        abi {
            enable true
            reset()
            //include  'armeabi', 'armeabi-v7a','arm64-v8a','x86','x86_64'
            include 'armeabi-v7a'
            universalApk true
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

完整的配置为:

android {
   ...
    defaultConfig {
       .....
        ndk {
            //选择要添加的对应cpu类型的.so库。
            //abiFilters 'armeabi','arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
            abiFilters 'armeabi-v7a'
            moduleName "app"
        }
    }
    splits {
        abi {
            enable true
            reset()
            //同时打包出多个cpu类型的apk
            //include  'armeabi', 'armeabi-v7a','arm64-v8a','x86','x86_64'
            include 'armeabi-v7a'
            universalApk true
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

总结

使用上述方法虽然可以解决java.lang.UnsatisfiedLinkError的问题,但是在程序的运行效率上会有所降低。若可以选择还是建议编译CPU直接支持的指令集而不是兼容的指令集。

参考:

https://developer.android.google.cn/ndk/guides/abis
https://www.zhihu.com/question/36893314/answer/78467097

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/143287
推荐阅读
相关标签
  

闽ICP备14008679号