zipalign对齐
什么是字节对齐?
所谓的字节对齐,就是数据是按照一定的规则在空间上排列,而不是按照内存空间的顺序一个接着一个排列。
比如说,N字节对齐,其含义是:数据存放的起始地址 % N == 0
对齐的优势?
数据对齐的根本原因是可以提高CPU访问数据的效率,因为可减少访问内存的次数,但问题是可能会产生额外的内存消耗。
需要字节对齐的根本原因在于CPU访问数据的效率问题。假设上面整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。 而如果变量在自然对齐位置上,则只要一次就可以取出数据。一些系统对对齐要求非常严格,比如sparc系统,如果取未对齐的数据会发生错误,而在x86上就不会出现错误,只是效率下降。 各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。 比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐,但其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。 比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。显然在读取效率上下降很多。 另外字节对齐的作用不仅是==便于cpu快速访问==,同时合理的利用字节对齐可以==有效地节省存储空间==。 也即CPU一次访问时,要么读0x01~0x04,要么读0x05~0x08…硬件不支持一次访问就读到0x02~0x05 例:如果0x02~0x05存了一个int,读取这个int就需要先读0x01~0x04,留下0x02~0x04的内容,再读0x05~0x08,留下0x05的内容,两部分拼接起来才能得到那个int的值,这样读一个int就要两次内存访问,效率就低了。
Android中的特定优势?
对齐后提高了的Applications与Android系统的交互效率,从而可以使整个系统的运行速度有了较大的提升。
原因是:Android系统中应用的数据都保存在它的APK文件中,这些文件经常会被多个进程访问。
比如:
- 安装程序通过每个apk的manifest文件获取与当前应用程序相关联的permissions信息
- Home程序读取当前APK的名称和图标等信息
- System server读取一些与应用运行相关信息
- APK所包含的内容不仅限于当前应用所使用,而且可以被其它的应用通过内容提供器调用
zipalign优化的最根本目的是帮助操作系统更高效率的根据请求索引资源,通过将apk中的未压缩数据进行字节对齐(一般为4字节对齐),允许系统使用mmap方法直接映射文件至内存空间,降低内存的消耗。
如何对齐?
zipalign从Android sdk 1.6开始支持。
一般来说,Android Studio会自动帮你进行zipalign相关的优化。
手动进行优化时,zipalign所在的位置为:sdk目录/build-tools/对应版本号,不同的Android版本对应着不同的zipalign工具。
具体如下:
进行对齐: zipalign [-f] [-v]
infile.apk outfile.apk
.
检查是否对齐: zipalign -c -v
existing.apk
alignment是一个定义字节对齐边界的整数。 这必须总是4(提供32位对齐),否则它什么也不做。
- -f:覆盖输出的文件
- -v:详细输出
- -p:outfile.apk应该对infile.apk中的所有共享对象文件使用相同的页面对齐
- -c:检查给定的文件是否对齐
apksigner VS jarsigner
apksigner是Android Build Tools从24.0.3版本引入的一个新的apk文件签名工具,用它可以替代以往一直在使用的jarsigner,而且只要apk文件的AndroidManifest声明支持的sdk范围包含24或者以上(就是安卓7.0或者以上),那么工具会自动为apk文件打入新的签名格式,名为APK Signature Scheme v2。
两种签名方式对zipalign的影响:
- 如果您使用apksigner,zipalign只能在签署APK文件之前执行。 如果您使用apksigner签署APK,并对APK进行进一步更改,则其签名将失效。
- 如果你使用jarsigner,zipalign只能在APK文件签名后才能执行。