Android基础(1)| 结构、APK、虚拟机

Android体系结构

原文:Android系统架构开篇 - 知乎 (zhihu.com)

APK基本结构

原文:安卓逆向之路 基础扫盲 - 沐风先生 - 博客园 (cnblogs.com)

#.apk是zip压缩包文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
assets           	静态资源文件(图片、音频、数据库、网页、配置文件等),不生成资源ID

res 资源文件,需要编译(布局),会出现在清单文件R.java(类)索引中

lib 各种平台下使用的对应的so文件,C++

libs

META-INF 签名文件

resources.arsc 资源索引表(映射),描述具ID值的资源配置信息

AndroidManifest.xml 清单文件(图标、界面、权限、入口)配置和声明

classes.dex 源代码,超过65535会进行分包处理,可通过反编译工具dex2jar转化成jar包。

#META-INF

#原文:Android生成APK后目录中META-INF目录文件解析 - 简书 (jianshu.com)

一个APK文件的后缀名从.apk改为.zip或者.rar,解压,META-INF目录下看到四个文件:MANIFEST.MF、CERT.SF、INDEX.LIST、CERT.RSA

MANIFEST.MF

​ 摘要文件,历APK包中的所有文件,对非文件夹非签名文件的文件,逐个用SHA1生成摘要信息,再用Base64进行编码。校验信息不同,程序将无法正常安装。

CERT.SF

​ 对于生成的MANIFEST.MF文件利用SHA1-RSA算法对开发者的私钥进行签名。在安装时只有公共密钥才能对其解密。解密之后将其与未加密的摘要信息进行比对,如果相符则文件没有被修改。

INDEX.LIST

​ APK索引文件目录

CERT.RSA

​ 保存公钥、加密算法等信息

JVM、DVM与ART

JVM

Java虚拟机,运行的是.java文件编译后的**.class文件**

Dalvik

Android4.4及以前使用的都是Dalvik虚拟机,我们知道Apk在打包的过程中会先将java等源码通过javac编译成.class文件,但是我们的Dalvik虚拟机只会执行**.dex文件,这个时候dx会将.class文件转换成Dalvik虚拟机执行的.dex文件。Dalvik虚拟机在启动的时候会先将.dex文件转换成快速运行的机器码,又因为65535这个问题,导致我们在应用冷启动的时候有一个合包的过程,最后导致的一个结果就是我们的app启动慢,这就是Dalvik虚拟机的JIT特性**。

ART

ART虚拟机是在Android5.0才开始使用的Android虚拟机,ART虚拟机必须要兼容Dalvik虚拟机的特性,但是ART有一个很好的特性AOT(ahead of time),这个特性就是我们在安装APK的时候就将dex直接处理成可直接供ART虚拟机使用的机器码,ART虚拟机将.dex文件转换成可直接运行的.oat文件,ART虚拟机天生支持多dex,所以也不会有一个合包的过程,所以ART虚拟机会很大的提升APP冷启动速度。

Xposed hook的是Java代码,所以Xposed不支持5.0以及以上系统。

APK打包流程

![img](https://img2020.cnblogs.com/blog/795445/202011/795445-20201107185648005-1582565761.png

APK安装流程

1
2
3
4
system/app	#系统自带应用程序,adb root权限才能删除
data/app #用户程序安装目录,安装时apk复制至此
data/data #存放应用程序数据
data/dalvik-cache #apk的dex文件安装到dalvik-cache目录下

安装:复制APK到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。

删除:扫描上述三个目录创建的文件及目录

虚拟机

原文:(9条消息) android 虚拟机介绍_旺仔的专栏-CSDN博客_安卓虚拟机

Java虚拟机

不是真实的物理机,JVM是一种用于计算设备的规范,没有寄存器,指令集是使用Java栈来存储中间数据

1
2
3
4
5
6
7
8
dalvik虚拟机与Java虚拟机区别:

1)dalvik基于寄存器,而JVM基于stack
2)Dalvik执行的是特有的DEX文件格式,而JVM运行的是*.class文件格式。
dalvik优势:
1)在编译时提前优化代码而不是等到运行时
2)虚拟机很小,使用的空间也小;被设计来满足可高效运行多种虚拟机实例。
3)常量池已被修改为只使用32位的索引,以 简化解释器

Dalvik虚拟机

指令集基于寄存器架构,执行其特有的文件格式——dex字节码,主要负责完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。

Dalvik进程管理

​ #android4.4以前

​ 依赖于linux的进程体系结构,Zygote是一个虚拟机进程,同时也是一个虚拟机实例的孵化器,它通过init进程启动。首先会孵化出System_Server(android绝大多系统服务的守护进程,它会监听socket等待请求命令,当有一个应用程序启动时,就会向它发出请求,zygote就会FORK出一个新的应用程序进程).每当系统要求执行一个android应用程序时,Zygote就会运用linux的FORK进制产生一个子进程来执行该应用程序。 #不同的应用在不同的进程空间里运行,最大程度的保护应用的安全和独立运行。

ART虚拟机

​ 为了降低应用的开发难度,并将其适配到不同硬件配置的设备上,在Linux内核之上构建了一个虚拟机,Android应用使用java开发,运行在虚拟机之上。AOT(Ahead-Of-Time)技术,会在应用程序安装时就转换成机器语言,不再在执行时解释,从而优化了应用运行的速度。在内存管理方面,对内存分配和回收都做了算法优化,降低了内存碎片化程度,回收时间也得以缩短。

内存管理

​ ART虚拟机首先会从系统空间中取得足够的空间,这些空间在没有使用的时候并不占用物理内存,在使用的时候才分配物理内存,在不需要的时候及时归还给系统。ART 将分配到的空间根据需要托管给不同的算法进行管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum AllocatorType {

kAllocatorTypeBumpPointer, // Use BumpPointer allocator, has entrypoints.

kAllocatorTypeTLAB, // Use TLAB allocator, has entrypoints.

kAllocatorTypeRosAlloc, // Use RosAlloc allocator, has entrypoints.

kAllocatorTypeDlMalloc, // Use dlmalloc allocator, has entrypoints.

kAllocatorTypeNonMoving, // Special allocator for non moving objects, doesn't have entrypoints.

kAllocatorTypeLOS, // Large object space, also doesn't have entrypoints.

};

**RosAlloc(Rows of slots Allocator)**:在Ros Alloc Space分配对象,是一种线性分配方式,将一个大的连续空间划分为多个片,每个片中只能分配固定大小的内存。这种分配方式有一个更加细粒度的结构,可以锁定独立的对象。

BumpPointer:在Bump Pointer Space中分配对象。每一次申请时,分配需要的size,返回end地址的值。然后将end后移sized,作为下一次申请的地址。这种分配采用不计数申请的方式,直到发生out of memory。采用Moving GC的方式进行回收。

**TLAB(Thread Local Allocation Block)**:在由Bump Pointer Space提供的线程局部分配缓冲区中分配对象,按线程进行管理。每一个线程,从Bump Pointer Space中申请一个block,在线程内使用Bump Pointer的分配策略。由于每一个线程独立在自己的block中分配内存,避免了同步,可以提高效率。减少了申请内存时线程之间的竞争。

DLMalloc:这是原Dalvik使用的算法 。在Dl Malloc Space分配对象,将memory划分成很多小的数据块,每一个块的前8个或者16个字节作为Header,使用链表来管理空闲的数据块。

​ 内存回收方面,ART也提供了几种GC算法,GC算法与内存分配算法相对应(后续再补)

代码执行
     Java文件在编译成class文件,然后经过Android平台的dx工具转换为Dex文件后,同Native code(JNI)和资源一起打包成apk,apk安装到手机后解压出Dex文件。Dalvik会通过dexopt工具将Dex优化,成为Odex文件,Odex文件的效率比Dex高,但其中大部分代码仍然需要每次执行时编译;而ART则会将Dex通过dex2oat工具编译得到一个ELF文件,它是一个可执行的文件。