`
shuai1234
  • 浏览: 971969 次
  • 性别: Icon_minigender_1
  • 来自: 山西
社区版块
存档分类
最新评论

Android 中与 so 有关的一个大坑

 
阅读更多

Android 应用开发中不可避免的会引入第三方的代码。如果是开源项目风险相对可控,如果引入商用的 SDK 那就要谨慎了,难免会有这样或那样的问题。比如我们今天要说的这一个。

这里写图片描述

对集成过第三方 SDK 的同学,上图中的目录结构应该不陌生。正常情况下我们只需要将不同版本的 so 文件分别放置。但如果我们要集成的这个第三方 SDK 偏偏没有 arm-v7a 的版本呢?是删除 armeabi-v7a 目录只保留 armeabi ?还是说两个目录下 .so 文件数不同也没有关系?系统会加载哪个 .so 呢?

如果只对结论感兴趣可以直接跳到最后

为了方便说明我们先引入 FAT Binary 的概念。我们知道不同的 CPU 支持的指令集也不一样,那么如果我们需要让 App 尽可能不同的 CPU 上都可以正常运行该怎么做呢?简单,只需要将不同版本的 Binary 放在一个文件里,运行时按需取用就可以了。这就是 FAT Binary 的典型实现。Android 实现 FAT 的方式有些不同,就是上边提到的将 .so 文件放置在相应文件夹中。在 Android 系统中 ndk 默认会生成如下 7 种 so。

这里写图片描述

在 apk 文件中带这么多版本的 .so 是一种很不经济的做法:

  • mips / mips64: 极少用于手机可以忽略
  • x86 / x86_64: x86 架构的手机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码工具,实现 对 arm .so 的兼容,再考虑 x86 1% 以下的市场占有率,x86 相关的两个 .so 也是可以忽略的
  • armeabi: ARM v5 这是相当老旧的一个版本,缺少对浮点数计算的硬件支持,在需要大量计算时有性能瓶颈
  • armeabi-v7a: ARM v7 目前主流版本
  • arm64-v8a: 64位支持

这样我们就可以明确 mips, mips64, x86, x86_64 这 4 个 .so 我们是不需要的。

我们回到开头提到的问题:

假定我们现在的情况是这样的(b.so 就是那个只有 armeabi 版本的第三方 so):

这里写图片描述

如果这样放置的话,在 ARM / ARM v7 两种设备上运行 apk 时会分别执行哪个 so 呢?

答案是:不确定……

这么坑爹的答案是怎么来的呢?

由于 Android 上 FAT binrary 的设计如此阳春,在 apk 安装时就需要根据 CPU 情况执行对应版本 so 的拷贝。对上边的情况最合理的一种做法应该是使用 armeabi-v7a/a.so 和 armeabi/b.so 这两个文件。Google 最初也是这么想的,然后就引入了 Bug…

Native library copy issue when install apk with different abi native libraries on device

这里写图片描述

上图是到 Android 4.4 还在使用的 so 文件拷贝逻辑,看起来没有问题?

坑爹是 Android 在安装 apk 文件时没有保证 zip entry 的扫描顺序,所以同样的文件放置会带来两种不同的安装结果:

这里写图片描述

这里写图片描述

看的有点头晕?简而言之,如果按我们上面的放置方式,安装后系统可能只拷贝了 armeabi-v7a/a.so。如果执行到 b.so 的逻辑,程序显然会 crash

这边还有个小插曲,这个 bug 的发现者在提交时其实已经给出了完善的解决方案,但在经历了快有小一年的 code review 后 Android 官方表示:我们自己另起炉灶修好了=_=。

这里写图片描述

这个问题确实在 Android 5.0 已经 “修复” 了。“修复” 方式简单粗暴,不再以文件为粒度匹配 abi,直接拷贝整个文件夹=_=。所以如果按我们之前的放置方法,在 Android 5.0+ 如果执行到 b.so 也是一定会 crash 的。

上面提到,只保留 armeabi 文件夹从性能角度是不明智的。正确的做法是将 armeabi/b.so 复制一份到 armeabi-v7a/b.so. 这是由于 ARM v7 是前向兼容 ARM v5 的。

  • 为了减小 apk 体积,只保留 armeabi 和 armeabi-v7a 两个文件夹,并保证这两个文件夹中 so 数量一致
  • 对只提供 armeabi 版本的第三方 so,原样复制一份到 armeabi-v7a 文件夹

原文地址:https://zhuanlan.zhihu.com/p/21359984

分享到:
评论

相关推荐

    Android TCP Socket通信实例Demo源码Apk下载

    最近有个项目模块需要用到TCP Socket通讯,遇到了一个大坑,所以做了这个Demo。 本Demo主要实现了安卓(Android)TCP 客户端(Client)和服务器(Server)Demo的Socket通讯。以及对接硬件的项目数据在十六进制&&byte&&int...

    大坑传统美食首推土鸡城,15年前上大坑,游客十之八九必.pdf

    【大坑传统美食首推土鸡城】是一个深受游客和美食爱好者欢迎的餐饮目的地,尤其在15年前,它已经成为台中大坑地区不可或缺的一部分。这个美食地标——“黑公羊土鸡城”,以其独特的土鸡料理和鲜美的地方特色菜肴而...

    搞定电脑故障 识破卖家大坑

    系统崩溃、蓝屏、程序运行异常等,这通常与操作系统、驱动程序或应用程序有关。学会安全模式启动、系统还原、重装系统等技巧,能帮助我们排查问题。同时,保持软件及时更新,安装杀毒软件防止病毒、恶意软件侵入,也...

    大坑旅游资讯网.pptx

    该网站由一个团队在杨子青老师的指导下开发完成,旨在整合大坑景点与周边商家信息,打造一个集电子地图、个性化旅游体验于一体的网络服务。 一、开发动机与目的 开发动机主要源于电子地图和旅游资讯的需求。专题...

    数字化转型12个大坑.docx

    然而,企业在转型过程中可能会遇到诸多挑战,以下12个大坑是企业在数字化转型时需要特别警惕的: 1. **不了解转型本质和目的**:企业必须清楚地认识到,数字化转型不仅仅是技术升级,更关乎企业整体战略的调整。...

    跨公网调用的大坑与架构优化方案

    3. **工作线程占用问题**:在一个服务中,若某接口因公网调用而发生超时,则该接口所占用的工作线程将在一段时间内无法释放,进而影响到其他正常运行的接口。 #### 二、优化方案 针对上述问题,本文提出了以下几种...

    “大坑湖”沧桑巨变.docx

    【大坑湖】的沧桑巨变反映了中国城市化进程中的一个重要环节——城市改造与经济发展。大坑湖曾是秦皇岛市的一个遗留问题,历经多年沉寂,最终在2003年华丽转身,变为金原国际商务大厦,成为了秦皇岛的标志性建筑。这...

    java配置GDAL库的大坑

    GDAL 库是一个开源的地理信息系统(GIS)库,提供了对栅格和矢量数据的支持。在 Java 中使用 GDAL 库需要将其配置到 Java 项目中,但是在配置过程中容易遇到版本不一致的问题。 GDAL 版本不一致的原因 GDAL 库有多...

    Android textview 实现长按自由选择复制功能的方法

    这里有一个大坑,我的viewGroup中有一个这个属性android:descendantFocusability=”blocksDescendants” 开始没有注意到,试了好多方法都不行,后来才看到这个属性,顺便科普一下,这个属性有三个值~ ...

    QT制作带有界面的静态库,并且调用时的一个大坑:可以获取窗口指针,但是show()时直接崩溃

    在QT编程中,创建带有界面的静态库是一个常见的需求,特别是在开发跨平台的应用程序时。然而,这个过程中可能会遇到一些陷阱,特别是在尝试显示界面时。本文将深入探讨标题和描述中提到的问题:“QT制作带有界面的...

    差旅费这5个税务大坑每个企业都存在.docx

    以下是五个企业在处理差旅费时常见的税务大坑: 1. **差旅费核算范围不当**:差旅费通常涵盖出差期间的交通、住宿和公杂费等,不应随意扩大范围。例如,送礼、款待客户、娱乐、健身、旅游等非业务必需的支出,应当...

    Jwt隐藏大坑,通过源码揭秘.doc

    在实际使用过程中,可能会遇到的一个陷阱是,如果 JWT 生成和验证过程中的编码不一致,会导致认证失败。例如,如果你的 JWT 生成库使用了标准的 Base64 编码,但验证时使用了 Base64Url 解码,或者反之,将会导致...

    es6 state&props设置大坑1

    在ES6的类语法中,处理`state`和`props`的方式与ES5有所不同,这可能会导致开发者遇到一些陷阱。让我们深入探讨一下这些变化以及如何正确地设置和使用`state`和`props`。 首先,`state`代表组件内部可变的状态,它...

    jboss4.0.5-GA在使用RMI时的大坑

    在描述中提到了一个博客链接,虽然没有具体内容,但通常博主会分享在实际操作中遇到的问题和解决方案。 JBOSS 4.0.5 GA是JBOSS应用服务器的一个早期版本,它是一个基于Java的开源应用服务器,广泛用于部署和管理...

    Android Data Binding 在 library module 中遇到错误及解决办法

    记一次 Data Binding 在 library module 中遇到的大坑 使用 Data Binding 也有半年多了,从最初的 setVariable,替换 findViewById,到比较高级的双向绑定,自定义 Adapter、Component,查看源码了解编译、运行流程...

    人生大坑:操别人的心太多,干自己的事太少.pdf

    - **成为领域专家**:文中举例通过深入研究一个特定领域的细节(如门头设计),并在该领域内积累足够的知识和经验,最终可以成为该领域的专家。 ### 5. 社区反馈 - **共鸣与反思**:社区成员对文中提到的观点表示...

    大坑仔水库工程施工设计方案.doc

    - 安全第一:在设计方案中,首要考虑的是施工过程中的人员安全,确保所有操作符合国家安全法规,避免事故的发生。 - 质量优先:工程质量是水库工程的生命线,设计必须遵循严格的质量标准和规范,确保工程长期稳定...

    lypeer:一名Android开发者的微信小程序填坑之路《上》

    之前基本没有前端开发经验,甚至连 JS ,HTML 都是为了开发小程序现学的一些皮毛——所以文章中所提到的一些点也许在资深前端开发者看来只是小case,但是站在一个 Android 开发者的角度来看确实是大坑。 前面就不说...

    第三章 跳过运营数据分析和挖掘的“大坑”1

    在运营数据分析和挖掘过程中,跳过“大坑”至关重要。聚类分析是一种常用的数据挖掘技术,旨在通过相似性将数据点分组,以揭示数据的内在结构。本章主要关注聚类分析中需要注意的问题,特别是数据异常和处理大规模...

Global site tag (gtag.js) - Google Analytics