移动安全-第四天 安卓编译,打包原理

正常的编译原理

按照google给出的编译步骤如下:

   1> source build/envsetup.sh:加载命令

   2> lunch:选择平台编译选项

   3> make:执行编译

https://www.cnblogs.com/shakin/p/4615872.html

java编译过程

Android的4种文件类型Java,class,dex,apk

Java文件-----应用程序源文件

Android本身相当一部分都是用java编写而成(基本上架构图里头蓝色的部份都是用Java开发的),android的
应用必须使用java来开发
 

Class文件------Java编译后的目标文件
不像J2se,java编译成class就可以直接运行,android平台上class文件不能直接在android上运行。 由于Google
使用了自己的Dalvik来运行应用, 所以这里的class也肯定不能在AndroidDalvik的java环境中运行, android
的class文件实际上只是编译过程中的中间目标文件,需要链接成dex文件后才能在dalvik上运行

Dex文件-----Android平台上的可执行文件
Android虚拟机Dalvik支持的字节码文件格式Google在新发布的Android平台上使用了自己的Dalvik虚拟机
来定义, 这种虚拟机执行的并非Java字节码, 而是另一种字节码: dex格式的字节码。在编译Java代码之后,
通过Android平台上的工具可以将Java字节码转换成Dex字节码。虽然Google称Dalvik是为了移动设备定
做的,但是业界很多人认为这是为了规避向sun申请Javalicense。这个DalvikVM针对手机程式/CPU做过最
佳化,可以同时执行许多VM而不会占用太多Resource。


Apk文件-------Android上的安装文件
Apk是Android安装包的扩展名,一个Android安装包包含了与某个Android应用程序相关的所有文件。apk
文件将AndroidManifest.xml文件、应用程序代码(.dex文件)、资源文件和其他文件打成一个压缩包。一个工
程只能打进一个.apk文件

来源: https://www.cnblogs.com/xgjblog/p/5809449.html

大概的意思是编译成java字节码之后可以在任何平台使用

下面是一些区别

java执行的流程

而后使用java虚拟机运行

加载的时候关键的就是如何加载和获取程序相关的文件等

加载之后需要进行执行的过程

将程序运行起来之后,就是数据的分布

上文已经说过dex文件和class文件的各自作用,下面是二者的比对

生成的过程

dex结构分成三部分:
文件头:表明了是dex文件,已经文件的大小等等数据
索引头:如下图所示
数据区:数据区,就像是jvm中的堆保存方法+变量。

https://www.jianshu.com/p/cfeb8dec53c3

// Raw header_item.
  struct Header {
    uint8_t magic_[8];
    uint32_t checksum_;  // See also location_checksum_
    uint8_t signature_[kSha1DigestSize];
    uint32_t file_size_;  // size of entire file
    uint32_t header_size_;  // offset to start of next section
    uint32_t endian_tag_;
    uint32_t link_size_;  // unused
    uint32_t link_off_;  // unused
    uint32_t map_off_;  // unused
    uint32_t string_ids_size_;  // number of StringIds
    uint32_t string_ids_off_;  // file offset of StringIds array
    uint32_t type_ids_size_;  // number of TypeIds, we don't support more than 65535
    uint32_t type_ids_off_;  // file offset of TypeIds array
    uint32_t proto_ids_size_;  // number of ProtoIds, we don't support more than 65535
    uint32_t proto_ids_off_;  // file offset of ProtoIds array
    uint32_t field_ids_size_;  // number of FieldIds
    uint32_t field_ids_off_;  // file offset of FieldIds array
    uint32_t method_ids_size_;  // number of MethodIds
    uint32_t method_ids_off_;  // file offset of MethodIds array
    uint32_t class_defs_size_;  // number of ClassDefs
    uint32_t class_defs_off_;  // file offset of ClassDef array
    uint32_t data_size_;  // unused
    uint32_t data_off_;  // unused
    ......
  }

file_size_: 整个文件的大小,单位字节
header_size_: 文件头的大小,单位字节
string_ids_size_: 字符串列表中字符串的数量
string_ids_off_: 字符串列表在文件中的偏移
type_ids_size_: 类型列表中元素数量
type_ids_off_: 类型列表在文件中的偏移
proto_ids_size_: 方法原型列表元素数量
proto_ids_off_: 方法原型列表在文件中的偏移
field_ids_size_: 字段列表的元素数量
field_ids_off_: 字段列表在文件中的偏移
method_ids_size_: 方法列表元素的数量
method_ids_off_: 方法列表在文件中的偏移
class_defs_size_: 类定义列表中元素数量
class_defs_off_: 类定义列表在文件中的偏移
data_size_: data段的大小
data_off_: data段在文件中的偏移

链接:https://www.jianshu.com/p/7afbadd6099f  具体的介绍 很多的

一个真实的例子

apk打包过程

Android安装包的后缀都是.apk, apk是Android Package的缩写。 解压apk文件后包含AndroidManifest.xml、assets目录、classes.dex(还可能有 classes2.dex,classes3.dex...classesN.dex)、lib目录、META-INF目录、res目录和resources.arsc。

    ndroidManifest.xml对应源代码中的AndroidManifest.xml, 但这里是编译过的,文件内容已经不同了。

     assets对应源代码的assets目录, 是直接复制过来的。

     classes.dex是包含所有Java文件对应的字节码。

     lib目录对应源代码中的libs目录,包含so文件。

     META-INF目录包含CERT.RSA、CERT.SF、MANIFEST.MF等, 保存了各个资源文件的SHA1值,用于校验资源文件是否被篡改,从而防止二次打包时资源文件被替换。

     res目录对应源码的res目录, 包含各种图片、xml等。

     resources.arsc包含了各个资源文件的映射, 可以理解为索引, 通过该文件能找到对应的资源文件信息。

(AAPT - Android Asset Packaging Tool AAPT是Android资源打包工具)资源打包的过程如下:

1.从图中我们可以看出
(1)除了assets和res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理「2」
(2)除了assets资源之外,其它的资源都会被赋予一个资源ID。包括res/raw也会有资源ID,即R.id.resourceId。
(3)打包工具负责编译和打包资源,编译完成之后,会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源ID常量。

这个在AS中我们编译的时候也看到了

还是没明白resources.arsc和R.java存在的意义?我们可以这样想,一个项目由代码和资源文件组成,代码通过对资源的处理来展现业务流程,那我们代码中肯定要获取到某个所需要的资源吧?Android为了方便管理,就定了一个文件,里面定义了各个专属资源ID常量,来表示我们项目中存在的资源。写代码的时候,我们要用某个资源,是不是都是类似这样写:
tvMrchNo = (TextView) findViewById(R.id.tv_mrch_no);

apk打包过程图,其中包括资源打包 代码的编译等 资源打包的方法在上边已经说过了这里主要是看流程

从上图中可以看到。完整的打包流程应该是:
(1)打包资源文件。
(2)处理aidl文件,生成相应java 文件。对于没有使用到aidl的android工程,可以跳过此步骤。
(3)编译工程源代码,生成相应class 文件。
这一步调用了javac编译工程src目录下所有的java源文件,生成的class文件位于工程的bin\classes目录下,上图假定编译工程源代码时程序是基于android SDK开发的,实际开发过程中,也有可能会使用android NDK来编译native代码,因此,如果可能的话,这一步还需要使用android NDK编译C/C++代码,当然,编译C/C++代码的步骤也可以提前到第一步或第二步。通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件。
(4)转换所有class文件,生成classes.dex文件。Android虚拟机的可执行文件为dex格式,所以需要此步骤。
(5)打包生成apk。打包后的res文件夹(除res/raw资源被原装不动地打包进APK之外)、打包后类文件(.dex文件)、libs文件(包括.so文件,当然很多工程都没有这样的文件,如果你不使用C/C++开发的话)、resources.arsc、assets、AndroidManifest.xml打包成apk文件。
(6)对apk文件进行签名。
(7)对签名后的apk文件进行对其处理。在 Android SDK 中包含一个名为 “zipalign” 的工具,它能够对打包后的 app 进行优化。 即对签名后的apk进行对齐处理。

另外一种图示结构,这里主要为了说明的是源码的编译流程

源码进行javac编程class文件 然后编译为dex文件,然后进行一系列处理,签名 优化等 最后生成可以打包apk文件

除了上述标注的,还有以下参考文章

https://www.jianshu.com/p/d29c37dda256

https://blog.csdn.net/brycegao321/article/details/79127159 

https://www.jianshu.com/p/7afbadd6099f

猜你喜欢

转载自blog.csdn.net/iamsongyu/article/details/88623298