Smali 语法
引言
-
大家都知道apk安装包其实就是个zip包,我们通过解压软件解压出来会看到里面的架构
-
assets
-
META_INF 存放签名信息
-
lib
- arm
- ...
-
res
-
AndroidManifest.xml
-
classes.dex Java代码编译得到的Dalvik VM能直接执行的文件
-
resources.arsc
-
asset和res资源目录的不同在于:
1. res目录下的资源文件在编译时会自动生成索引文件(R.java),assets的资源文件不需要生成索引,在Java代码中需要用AssetManager来访问 2. 一般来说,除了音频和视频资源(需要放在raw或asset下),使用Java开发的Android工程使用到的资源文件都会放在res下;使用C++游戏引擎(或使用Lua binding等)的资源文件均需要放在assets下。
Dalvik
- Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。 它可以支持已转换为 .dex格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。 Dalvik 经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik 应用作为一个独立的Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。
Dalvik和JVM 的关系
- Dalvik是基于寄存器的,而JVM是基于栈的。Dalvik运行dex文件,而JVM运行java字节码自Android 2.2开始,Dalvik支持JIT(just-in-time,即时编译技术)。优化后的Dalvik较其他标准虚拟机存在一些不同特性:
- 1.占用更少空间
- 2.为简化翻译,常量池只使用32位索引
- 3.标准Java字节码实行8位堆栈指令,Dalvik使用16位指令集直接作用于局部变量。局部变量通常来自4位的“虚拟寄存器”区。这样减少了Dalvik的指令计数,提高了翻译速度。 当Android启动时,Dalvik VM 监视所有的程序(APK),并且创建依存关系树,为每个程序优化代码并存储在Dalvik缓存中。Dalvik第一次加载后会生成Cache文件,以提供下次快速加载,所以第一次会很慢。Dalvik解释器采用预先算好的Goto地址,每个指令对内存的访问都在64字节边界上对齐。这样可以节省一个指令后进行查表的时间。为了强化功能, Dalvik还提供了快速翻译器(Fast Interpreter)。
ART
-
Android Runtime
ART 的机制与 Dalvik 不同。在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT,Ahead-Of-Time)。这样的话,应用的启动(首次)和执行都会变得更加快速。
-
优缺点
优点:
- 1、系统性能的显著提升。 - 2、应用启动更快、运行更快、体验更流畅、触感反馈更及时。 - 3、更长的电池续航能力。 - 4、支持更低的硬件。
缺点:
- 1.机器码占用的存储空间更大,字节码变为机器码之后,可能会增加10%-20%(不过在应用包中,可执行的代码常常只是一部分。比如最新的 Google+ APK 是 28.3 MB,但是代码只有 6.9 MB。) - 2.应用的安装时间会变长。
一 Smali语法:Registers(寄存器)
-
引言
在Dalvik字节码中,寄存器都是32位的,能够支持任何类型。64位类型(Long和Double型)用2个寄存器表示。有两种方式指定一个方法中有多少寄存器是可用的。.registers指令指定了方法中寄存器的总数。.locals指令表明了方法中非参寄存器的数量。
-
寄存器命名方式
V命名方式和P命名方式。P命名方式中的第一个寄存器就是方法中的第一个参数寄存器。
-
敲黑板 举例说明: 如果一个方法有3个参数,5个寄存器 表示方法如下
- v0 the first local Register - v1 the second local Register - v2 p1 the first parameter Register - v3 p2 the second parameter Register - v4 p3 the thrid parameter Register
你可以用任何一种方式来引用参数寄存器——他们没有任何差别。
-
Smali 语法
-
数据类型
JAVA 对比 Smali
- byte B - boolean Z - int I - float F - long J 64bit 两个寄存器 - double D 64bit 两个寄存器 - short S - char C - void V - Object L L 代表对象 注意区别 long - Array [
对象类型
L可以表示java类型中的任何类.在java代码中以package.name.ObjectName的方式引用,而在Davilk中其描述则是以Lpackage/name/ObjectName;的形式表示.L即上面定义的JAVA类类型,表示后面跟着的是类的全限定名.比如java中的java.lang.String对应的描述--> Ljava/lang/String
数组类型
"[" 类型用来表示所有基本类型的数组,"["后跟着是基本类型的描述符.每一维度使用一个前置的"[", 比如java中的int[] 用汇编码表示便是**[I**;二维数组int[][]为[[I,三维数组则用**[[[I**表示.
对于对象数组来说,"["后跟着对应类的全限定符.比如java当中的String[]对应的是[java/lang/String;.
-
字段描述
基本类型和引用类型,不过两种类型引用格式类型相同
- 对象类型描述符->字段名:类型描述符 - eg:比如org.professor.demo 里面个Test类,该类中有两个变量,一个为int 一个为String Lorg/professor/demo/Test;->name:Ljava/lang/String; Lorg/professor/demo/Test;->age:I
-
方法描述
JAVA中方法的签名包括方法名,参数及返回值,在Smali相应的描述规则为:
对象类型描述符->方法名(参数类型描述符)返回值类型描述符 eg: java方法:public char charAt(int index){...} Davilk描述:Ljava/lang/String;->charAt(I)C java方法:public void getChars(int srcBegin,int srcEnd,char dst[],int dstBegin){...} Davilk描述:Ljava/lang/String;->getChars(II[CI)V java方法:public boolean equals(Object anObject){...} Davilk描述:Ljava/lang/String;->equals(Ljava/lang/Object)Z