本文基于Android 7.1,不过因为从BSP拿到的版本略有区别,所以本文提到的源码未必与读者找到的源码完全一致。本文在提供源码片断时,将按照 <源码相对android工程的路径>:<行号> <类名> <函数名> 的方式,如果行号对不上,请参考类名和函数名来找到对应的源码。
了解ART的基本运作原理,就需要了解ART编译出的代码是怎么运行的。我们将使用oatdump得到的代码,进行仔细分析。
从简单示例出发
以一个非常简单的函数为例:
frameworks/base/core/java/android/app/Activity.java:988
988 public void onCreate(@Nullable Bundle savedInstanceState,
989 @Nullable PersistableBundle persistentState) {
990 onCreate(savedInstanceState);
991 }
这个函数,仅仅是调用了同名的onCreate函数的实现。
编译成oat文件后(存放在boot.oat内),用oatdump出来,我找到对应的dex代码
129: void android.app.Activity.onCreate(android.os.Bundle, android.os.PersistableBundle) (dex_method_idx=2085)
DEX CODE:
0x0000: 6e20 2408 1000 | invoke-virtual {v0, v1}, void android.app.Activity.onCreate(android.os.Bundle) // method@2084
0x0003: 0e00 | return-void
这个dex代码看起来也非常简单。
接下来,我们看看编译出的机器码,反汇编后是什么:
QuickMethodFrameInfo
frame_size_in_bytes: 48
core_spill_mask: 0x000040e0 (r5, r6, r7, r14)
fp_spill_mask: 0x00000000
vr_stack_locations:
ins: v0[sp + #52] v1[sp + #56] v2[sp + #60]
method*: v3[sp + #0]
outs: v0[sp + #4] v1[sp + #8]
CODE: (code_offset=0x0337a6d5 size_offset=0x0337a6d0 size=66)...
0x0337a6d4: f5ad5c00 sub r12, sp, #8192
0x0337a6d8: f8dcc000 ldr.w r12, [r12, #0]
StackMap [native_pc=0x337a6dd] (dex_pc=0x0, native_pc_offset=0x8, dex_register_map_offset=0xffffffff, inline_info_offset=0xffffffff, register_mask=0x0, stack_mask=0b000000)
0x0337a6dc: b5e0 push {
r5, r6, r7, lr}
0x0337a6de: b088 sub sp, sp, #32
0x0337a6e0: 9000 str r0, [sp, #0]
0x0337a6e2: f8b9c000 ldrh.w r12, [r9, #0] ; state_and_flags
0x0337a6e6: f1bc0f00 cmp.w r12, #0
0x0337a6ea: d10a bne +20 (0x0337a702)
0x0337a6ec: 461d mov r5, r3
0x0337a6ee: 460e mov r6, r1
0x0337a6f0: 4617 mov r7, r2
0x0337a6f2: 6808 ldr r0, [r1, #0]
0x0337a6f4: f8d004c8 ldr.w r0, [r0, #1224]
0x0337a6f8: f8d0e020 ldr.w lr, [r0, #32]
0x0337a6fc: 47f0 blx lr
StackMap [native_pc=0x337a6ff] (dex_pc=0x0, native_pc_offset=0x2a, dex_register_map_offset=0x0, inline_info_offset=0xffffffff, register_mask=0xe0, stack_mask=0b000000)
v0: in register (6) [entry 0]
v1: in register (7) [entry 1]
v2: in register (5) [entry 2]
0x0337a6fe: b008 add sp, sp, #32
0x0337a700: bde0 pop {
r5, r6, r7, pc}
0x0337a702: 9103 str r1, [sp,