常见Android编译优化问题梳理总结

目录
  • 编译常见问题
  • 踩坑1
  • 踩坑2

编译常见问题

在开发过程中,有碰到过一些由于编译优化导致的代码修改并不符合我们预期的情况。这也就是之前为什么我经常说编译产物其实是不太可以被信任的。

  • 方法签名变更,底层仓库的方法变更但是上层模块并没有跟随一起重新编译导致的这个问题。
  • 常量优化,将一些常量的调用点直接替换成常量的值。
  • 删除空导包, 没有用的一些导包就会做一次剔除。

踩坑1

我们最近碰到一个 pipeline 相关而且很妖怪的问题。我们一个 pipeline 会检查apk产物中是否存在异常的方法调用,就是之前介绍的在R8的基础上开发出来的A8。但是最近有一个类被删除了之后呢,但是代码中还有一处调用点。但是这个检测竟然被通过了,然后这部分代码就被合入了master。

这个引用的文件就如上图所示,是一个 debug buildType 中的,所以并不是所有的apk中都会存在这部分代码。

然后呢,这个 MergeRequest 就被合入了 master 分支,因为当天是我们出下一个版本包的时间,然后交付给测试的就是全量编译的 debug 和 release 包。别的开发同学rebase完master之后就发现 piepline 都跑不过了,就导致了他们当天的代码无法被合入。

这个就是事情大概的起因和经过,但是各位有没有想过为什么会发生这个问题吗。这个是不是我们的 pipeline 出现了bug,导致了这种问题无法被识别出来了呢。

以前有说过,如果简单的说我们的快编系统就是把模块替换成对应的aar,从而达到编译提速。所以因为我们使用的是这个模块对应的aar产物,所以大概率就是因为这个模块的编译产物和源代码有差异导致了这个问题。

其实这个问题一出现我就已经知道大概率是由空导包优化导致的这个问题,因为在 pipeline 检查的时候,检测的apk产物中确实不存在这个导包。因为我们使用的是一个历史版本的aar,其中无效导包的部分已经被编译器做了删除空导包的优化了。接下来我们看下我写的一个demo中的无效导包。

图一呢是源代码java文件,图二呢则是jar包中的代码。可以简单的看出来行号呢是可以对应的上的,但是这个 AppCompatActivity 的无效导包在产物中已经被优化掉了。这里也就回答了在编译过程中会保留行号,但是也会优化掉一部分不需要的代码,让我们编译出来的产物更小。

所以也就导致了我们的产物和我们的源代码之间的差异,另外一个角度就是说从apk中我们确实是不存在这个类的导包。但是呢在我们把这部分代码重新编译成aar的时候,就会出现source缺失,导致的语法树无法生成,之后导致的编译失败问题。

这也就是所以我一直和大家说编译产物是不可以被信任的呢。

踩坑2

这个是之前的一个故事了,我们之前呢在模块中定义了一些静态常量吧,然后用来标识当前SDK的版本,然后这个值在别的模块中被引用到了。

有一次因为需求变更,我们更改了这个静态变量的值,然后呢我就把这个需求提测了。之后测试反馈给我为什么这边的这个值没有变化啊。

我的天,当时我就是这样,发生了什么情况。然后呢我全量打了个包好了,我当时也就以为只是编译时的一个bug而已。然后后来呢,我查了下资料发现这个就是一个java编译时的常量优化问题。过了一阵子吧,我面试了下字节跳动,然后我和面试官也聊了下这个话题,然后呢在这个方法签名变更的问题上,当时我略输一筹,哈哈哈哈。接下来我们就看下一个demo。

图1呢也是java代码,图2呢则是aar中的编译产物。其中我们可以看到,这个静态常量在编译成产物之后就会被编译成这样。

所以这个就解释了我一开始碰到的这个问题,他就是由于我们的编译器已经把aar中的这部分静态常量编译成了直接的值,然后呢我们的源变化之后如果没有重新编译对应的模块,就会导致这个值一直无法被更新到最新的值。

到此这篇关于常见Android编译优化问题梳理总结的文章就介绍到这了,更多相关Android编译优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android系统优化Ninja加快编译

    目录 背景 环境 关键编译阶段和耗时分析 阶段一:Soong bootstrap 阶段二:Kati遍历.mk搜集与ninja生成 阶段三:Ninja编译 编译优化 对比汇总 背景 Android系统模块代码的编译实在是太耗时了,即使寥寥几行代码的修改,也能让一台具有足够性能的编译服务器工作十几分钟以上(模块单编),只为编出一些几兆大小的jar和dex. 这里探究的是系统完成过一次整编后进行的模块单编,即m.mm.mmm等命令. 除此之外,一些不会更新源码.编译配置等文件的内容的操作,如touch

  • 哔哩哔哩Android项目编译优化

    目录 背景 编译优化 工作流程 快编插件 获取工程树结构 version版本 源码orAAR 主动Skip模块 Configuration策略 远端upload R8 class check Faster 云编译 独立的编译单元 展望 结语 背景 哔哩哔哩的安卓项目的工程结构是Monorepo(单仓)变种,也就是所有的代码都在一个工程结构下编译.我们认为Monorepo(单仓)是一个非常适合我们的开发模式,主要是因为其提供的原子提交,可见性,参与度,切片的稳定性等等优点,这些都是我们选择Mono

  • Android Studio通过Artifactory搭建本地仓库优化编译速度的方法

    Android Studio 编译速度慢,一般来说,原因有下面几个. Gradle下载慢 依赖库下载慢 依赖库使用"+"(使用最新的),每次都需要去查找新的(尽量不适用这种方式) 这里,大部分的库,我们可以通过阿里云代理仓库. 但是,如果有我们自己的私有库或者插件的话.肯定不希望放到阿里云上了. 这个时候,我们就需要建立,我们自己的本地仓库,让私有仓库,依赖阿里云的私有仓库. 依赖关系,如下图 这样,既保证了我们私有库的安全性,又让我们的依赖库也享受到了阿里云代理仓库的便利. 通过Ar

  • 常见Android编译优化问题梳理总结

    目录 编译常见问题 踩坑1 踩坑2 编译常见问题 在开发过程中,有碰到过一些由于编译优化导致的代码修改并不符合我们预期的情况.这也就是之前为什么我经常说编译产物其实是不太可以被信任的. 方法签名变更,底层仓库的方法变更但是上层模块并没有跟随一起重新编译导致的这个问题. 常量优化,将一些常量的调用点直接替换成常量的值. 删除空导包, 没有用的一些导包就会做一次剔除. 踩坑1 我们最近碰到一个 pipeline 相关而且很妖怪的问题.我们一个 pipeline 会检查apk产物中是否存在异常的方法调

  • Android 内存优化知识点梳理总结

    目录 RAM 和 ROM 常见内存问题 内存溢出 内存泄漏 常见内存泄漏场景 静态变量或单例持有对象 非静态内部类的实例生命周期比外部类更长导致的内存泄漏 Handler 导致的内存泄漏 postDelayed 导致的内存泄漏 View 的生命周期大于 Activity 时导致的内存泄漏 集合中的对象未释放导致内存泄漏 WebView 导致的内存泄漏 内存抖动 解决方案 其他优化点 App 内存过低时主动清理 前言: Android 操作系统给每个进程都会分配指定额度的内存空间,App 使用内存

  • Android 性能优化实现全量编译提速的黑科技

    目录 一.背景描述 二.效果展示 2.1.测试项目介绍 三.思路问题分析与模块搭建: 3.1.思路问题分析 3.2.模块搭建 四.问题解决与实 编译流程启动,需要找到哪一个 module做了修改 module 依赖关系获取 module 依赖关系 project 替换成 aar 技术方案 hook 编译流程 五.一天一个小惊喜( bug 较多) 5.1 output 没有打包出 aar 5.2 发现运行起来后存在多个 jar 包重复问题 5.3 发现 aar/jar 存在多种依赖方式 5.4 发

  • 浅谈Android性能优化之内存优化

    1.Android内存管理机制 1.1 Java内存分配模型 先上一张JVM将内存划分区域的图 程序计数器:存储当前线程执行目标方法执行到第几行. 栈内存:Java栈中存放的是一个个栈帧,每个栈帧对应一个被调用的方法.栈帧包括局部标量表, 操作数栈. 本地方法栈:本地方法栈主要是为执行本地方法服务的.而Java栈是为执行Java方法服务的. 方法区:该区域被线程共享.主要存储每个类的信息(类名,方法信息,字段信息等).静态变量,常量,以及编译器编译后的代码等. 堆:Java中的堆是被线程共享的,

  • 详解Android性能优化之启动优化

    1.为什么要进行启动优化 网上流行一种说法,就是8秒定律,意思是说,如果用户在打开一个页面,在8秒的时间内还没有打开,那么用户大概的会放弃掉,意味着一个用户的流失.从这里就可以看出,启动优化的重要性了. 2.启动的分类 2.1 冷启动 先来看看冷启动的流程图 从图中可以看出,APP启动的过程是:ActivityManagerProxy 通过IPC来调用AMS(ActivityManagerService),AMS通过IPC启动一个APP进程,ApplicationThread通过反射来创建App

  • Android布局优化之ViewStub控件

    ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的View,与其他的控件一样,有着自己的属性及特定的方法.当ViewStub使用在布局文件中时,当程序inflate布局文件时,ViewStub本身也会被解析,且占据内存控件,但是与其他控件相比,主要区别体现在以下几点: 1.当布局文件inflate时,ViewStub控件虽然也占据内存,但是相相比于其他控

  • Android内存优化杂谈

    Android内存优化是我们性能优化工作中比较重要的一环,这里其实主要包括两方面的工作: 1.优化RAM,即降低运行时内存.这里的目的是防止程序发生OOM异常,以及降低程序由于内存过大被LMK机制杀死的概率.另一方面,不合理的内存使用会使GC大大增多,从而导致程序变卡. 2.优化ROM,即降低程序占ROM的体积.这里主要是为了降低程序占用的空间,防止由于ROM空间不足导致程序无法安装. 本文的着重点为第一点,总结概述降低应用运行内存的技巧.在这里我们不再细述PSS.USS等概念与Android应

  • iOS开发教程之常见的性能优化技巧

    前言 性能问题的主要原因是什么,原因有相同的,也有不同的,但归根到底,不外乎内存使用.代码效率.合适的策略逻辑.代码质量.安装包体积这一类问题. 但从用户体验的角度去思考,当我们置身处地得把自己当做用户去玩一款应用时候,那么都会在意什么呢?假如正在玩一款手游,首先一定不希望玩着玩着突然闪退,然后就是不希望卡顿,其次就是耗电和耗流量不希望太严重,最后就是安装包希望能小一点.简单归类如下: 快:使用时避免出现卡顿,响应速度快,减少用户等待的时间,满足用户期望. 稳:不要在用户使用过程中崩溃和无响应.

  • android布局优化的一些实用建议

    前言 Android的绘制优化其实可以分为两个部分,即布局(UI)优化和卡顿优化,而布局优化的核心问题就是要解决因布局渲染性能不佳而导致应用卡顿的问题,所以它可以认为是卡顿优化的一个子集. 本文主要包括以下内容 为什么要进行布局优化及android绘制,布局加载原理 获取布局文件加载耗时的方法 介绍一些布局优化的手段与方法 一些常规优化手段 为什么要进行布局优化? 为什么要进行布局优化?答案是显而易见的,如果布局嵌套过深,或者其他原因导致布局渲染性能不佳,可能会导致应用卡顿 那么布局到底是如何导

随机推荐