Smali是一种有些像汇编的用于表示Dalvik VM的bytecode的语言。(readable aem-liked format for dalvik bytecode)。 Smali最早应该来自于 smali/baksmali 汇编/反汇编工具项目,并逐渐由开源社区完善。

在整个Android的程序运行时中:

Java Bytecode → DEX Bytecode

  1. Java/Kotlin源代码
  2. Java bytecode (.class files) using javac.
  3. Dalvik bytecode (.dex files) using dx or D8/R8
  4. Natice code

ART Compiles DEX Bytecode → Native Machine Code

不同于JVM的 JIT 动态编译,ART会将dex bytecode预编译为native code机器码,这一AOT (Ahead of Time)编译过程在Android应用安装时发生。

Types 类型

众所周知JVM是stack-based的虚拟机,Dalvik是register-based。stack-based和register-based最主要的区别是,他们管理 operands 操作数的方式不同。JVM使用 stack,而 Dalvik 使用虚拟的寄存器,两者都储存在 RAM 中。最终,这两种虚拟机将他们的bytecode编译为机器码,使用CPU的寄存器。

例如,以下是 5 + 3 的Java代码:

int a = 5;
int b = 3;
int c = a + b;

的JVM bycode:

iconst_5    // Push 5 onto the stack
istore_1    // Store 5 in variable 'a'
iconst_3    // Push 3 onto the stack
istore_2    // Store 3 in variable 'b'
iload_1     // Load 'a' (5) onto the stack
iload_2     // Load 'b' (3) onto the stack
iadd        // Pop top two values (5, 3), add them, push result (8)
istore_3    // Store result (8) in 'c'

How the stack changes:

StepStack StateAction
1[5]iconst_5
2[]istore_1 (stores 5 in var a)
3[3]iconst_3
4[]istore_2 (stores 3 in var b)
5[5]iload_1 (loads a)
6[5, 3]iload_2 (loads b)
7[8]iadd (pops 5 and 3, pushes 8)
8[]istore_3 (stores 8 in c)

以下是Dalvik bytecode:

const/4 v0, 5    // Store 5 in register v0  
const/4 v1, 3    // Store 3 in register v1  
add-int v2, v0, v1  // v2 = v0 + v1  

register-based bytecode 相比较 stack-based 能更快地被映射到 CPU registers 当中。

在 Dalvik 中,寄存器通常只有 32 bit,对于 64-bit type(如long, double)则需要两个寄存器进行储存。

.method public static add(II)I
    .registers 2
    add-int v0, p0, p1  # v0 = p0 + p1
    return v0
.end method