- 原标题: The Perils of Loading Native Libraries on Android
- 原文地址:medium.com/keepsafe-en…
- 原文作者: Hilal Alsibai
- 原文发布时间:2015年11月7日
笔者在去年java编译器遇到一个问题:项目打包成apk
文件后安装正常,打包成aab
文件后,通过bundleTool
解析成apk
文件后MMKV
初始化崩溃,但是将aab
文件上传到googlePlay
后,解析成apk
文件下载安装又正常。
通过阅读本文,你可以了解到为什么会出现这个问题,以及这个问题的解决思路。
译文
早在2012google网站登录入口
年,KeepSafe初期,我们试图approach为我们的Android
应用程序实施加密方案。通过多次迭代和原型,我们通过利用JNI(Java 原生接口)的强大功能找到了一google网站登录入口个最佳点。我们决定将接口写入我们在Java
中使用的加密库中,通过JNI
调用该库仅用于加密和解密的目的。我们选择了即时解决方案,尽Android可能减少对用户体验的影响。一旦google网站登录入口我们对我们的解决方案感到满意,我们决定将其部署到我们的生产应用程序中。我们严格测试了android下载我们的代码,并相信一切都会顺利进行,但是,appetite事情最后超出了我们的控制。
Unsatisandroidstudio安装教程fiedLinkEandroid下载rror
初现
当我们在发布后焦急地更新崩溃报告时,架构师工资我们开始注架构图怎么制作意到google网站登录入口一个反复出现的错误。用户遇到了UnsatisfiedLinkError
,这意味着有两种可能:(1)我们调用的本机架构是什么意思库不存在;(2)我们调用的本机方法不存在。由于第二种几乎总是通过编译和基本测试被捕获,此刻我们对用户的安装没有我们在APK
中提供的soAPP
本地库这一事google实感到困惑。
以下是一些日志文件:
java.lang.UnsatisfiedLinkError: Couldn’t load stlport_shared from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.kii.safe-1.apk,libraryPath=/data/app-lib/com.kii.safe-1]: findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:365)
at java.lang.System.loadLibrary(System.java:535)
at com.kii.safe.Native.<clinit>(Native.java:16)
… 63 more
Caused by: java.lang.UnsatisfiedLinkError: Library stlport_shared not found
at java.lang.Runtime.loadLibrary(Runtime.java:461)
at java.lang.System.loadLibrary(System.java:557)
at com.kii.safe.Native.<clinit>(Native.java:16)
… 5 more
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: get_lib_extents[760]: 1305 — /mnt/asec/com.kii.safe-1/lib/libstlport_shared.so is not a valid ELF object
at java.lang.Runtime.loadLibrary(Runtime.java:434)
at java.lang.System.loadLibrary(System.java:554)
at com.kii.safe.Native.<clinit>(Native.java:15)
Caused by: java.lang.UnsatisfiedLinkError: Library cryptopp not found
at java.lang.Runtime.loadLibrary(Runtime.java:461)
at java.lang.System.loadLibrary(System.java:557)
at com.kii.safe.Native.<clinit>(Native.java:17)
令人十分气愤的是
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: 1748 cannot locate ‘쯰f10Ⱉ夘.闑㥁뭫ර⓻^3c`+W#?-B꼠’…
at java.lang.Runtime.loadLibrary(Runtime.java:370)
at java.lang.System.loadLibrary(System.java:535)
at com.kii.safe.Native.<clinit>(Native.java:17)
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1312]: 1327 cannot locate ‘P#X #X #X #X #X #X#X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X #X#X #X #X #X #X #X #X #
at java.lang.Runtime.loadLibrary(Runtime.java:434)
at java.lang.System.loadLibrary(System.java:554)
at com.kii.safe.Native.<clinit>(Native.java:17)
没Java有明确的模式说明哪个库有问题,因为似乎所有so
库都在抛出异常。它不是特定于Android
版本的,它不仅发生在特定设备上。此外,在某些情况下,一些本机库被正确加载,但不是全部。在这一点上,我们在appstore互联网上疯狂地寻找答案或帮google助,结果却空手而归。我们开始发布修补程序,其中大部架构是什么意思分是推测性修补程序googleplay安卓版下载、额外的跟踪数据,以便我们更好地了解崩溃发生时的确切环境,以及专门检查预期安装位置中的本机库的一段代码。
此外,在某些情况下,一些本机库android下载被正确加载,但不是全部。
我们收集到的信息显示本地库不存在。系统类或文件系统错误并appear不是什么奇怪的侥幸,但是该用户的设备看起来很正常。 我们有了以下几点思路:
(1) 用户设备空间不足
当我们android什么意思考虑到这个异常的可能原因时,我们开始认为也许人们只是没有空间来正确安装本机库,因此它从未安装过。在尝试加载库之前进行快速诊断检查很快就证明了这个想法是错误的。用户在他们的设备上有足够的空间来存放我们正在运送的库。
(2)so
库未包含在架构图模板更新中
造成我们问题的第二个可能原因是Google Play
在向用户设备提供APK
时破坏了我们的APK
。在阅读了诸如此类的报告后,我们对这个想法有了一些支持,详细说明Google Play
应该向所有受问题影响的应用程序开发人google商店员发出通知,该问题导致用户在更新后无法启动他们的应用程序,因为本地库安装不正确。唯一的问题是这份报告是在8
月发布的,而我们在几个月架构设计后才开始处理这个问题。我们也从未收到来自Google Play
的通知,提到他们有任何错误。当然,这是很难验证的。
(3)直接与真实用户一起调试问题
由于我们无法在appstore手头的10
多种不同设备上重现该问题,因此我们决定联系遇到问题的用户。一位用户慷慨地决定帮助我们,并指出该应用程序在最新更新之前运行良好。这里的问题是,Android用户注意到的应用程序版本是一个包含我们的android的drawable类加密代码和本机库的版本,这只是为了增加我们的困惑和总体难题。我们决定直接向用户提供一个APK
文件,我们在其中验证了所有本机库都存在于APK
文件中。用户安装了架构APK
,启动了应用程序,然后又直接遇到了同样的UnsatisfiedLinkError
异常。这证实了不是Google Play
的问题,问题在于Android
的PackaapplicationgeManager
安装过程。
找到解决方案
由于我们发现问题出在安装过程中,因此我们决定复制安装过程中提取应用程序代码中的本机库的部分。幸运的是,您可以通过以下方式轻松获取设备上应用程序APK
文apple件的引用
Context.getApplicationInfo().sourceDir;
然后我们将使用它来将本机库提取到内javascript部存储android是什么系统位置。由于APK
文件只是ZIP
文件,因此只需编写一些ZIP
提取代码即可。我们迅速实现了提取代码并发货,导致崩Android溃数量大幅下降!每天抛出的 UnsatisfiedLinkError
异常总数如图:
为了减少我们的AappointmentPK
大小并确android平板电脑价格保我们的应用程序可以在所有可能的设备上运行,我们为x86
、androidstudio安装教程Armvappearance7
和 Arm
架java编译器构设计了我们Google的应用程序。每种风格只包含与其各自架构对应的本机库,因此完全有可能有人可以安装不是为他们的设备架构制作的APK
。
我们开始approach在崩溃中记录安装程序包名称,并很快发现,android是什么手机牌子是的,用户正在从各种来源安装应用程序,approach并且每个新的UnsatisfiedLinkError
都来自手动安装google的应用程序,用户错误地为他们的设备安装了错误的abi
架构。这是最后的“陷阱”,我们松了一口气,因为它有一个非常简单的android的drawable类解释。
介绍ReLinker
我们决定将提取代码打包成一个大家都可以使用的小库。任何人都不应该经历我们所经历的调试过程,尤其是当它涉及到一个非常基本的Android
功能时,它不在App
开发人员的控制范围内。
使用ReLinker
就像替换标准一样简单
System.loadLibrary(“mylibrary”);
使用java语言回调
ReLinker.loadLibrary(context, “mylibrary”)
ReLin架构图ker 源码
结语
在发布修复程序时,遇到此崩溃的人数持续达到约100,000
名用户。我们希望您会发现Reandroid/yunosLinker
很有用,并且永远不会再随机遇到UnsatisfiedLinkerError
。
译者话
其实框架做的apple事情很简单,在我们需要加载so
的时候,找到apk
文件内指定位置的so
文件加载,并且优化了so
的ABI
适配,进而解决了UnsaappstoretisfiedLinkError
。不过这种偏底层的问题确实是我们平时不容易遇到的。
- 解析apk文件的
so
文件,可以查看ApkLibraryInstaller
- 加载so文件,可以查看
SystemLibraryLoader