Android ART运作流程

你写的 Java 代码在 Android 上到底是怎么跑的?从 DEX 到机器码,ART 编译、加载、执行、GC 全链路拆解(附 dex2oat 实战调优)

目录

  • [一、ART 之前:Dalvik 为什么被换掉了](#一、ART 之前:Dalvik 为什么被换掉了)
  • [二、ART 的三种编译模式](#二、ART 的三种编译模式)
  • [三、AOT 编译:dex2oat 怎么把 DEX 变成机器码](#三、AOT 编译:dex2oat 怎么把 DEX 变成机器码)
  • [四、JIT 编译:运行时热点优化](#四、JIT 编译:运行时热点优化)
  • [五、混合编译:AOT + JIT 一起干活的全周期](#五、混合编译:AOT + JIT 一起干活的全周期)
  • [六、ART 怎么加载一个类](#六、ART 怎么加载一个类)
  • [七、一个方法在 ART 里的执行路径](#七、一个方法在 ART 里的执行路径)
  • [八、GC 垃圾回收](#八、GC 垃圾回收)
  • [九、.vdex / .odex / .art 三种文件分别是干嘛的](#九、.vdex / .odex / .art 三种文件分别是干嘛的)
  • [十、实战:看 App 的编译状态](#十、实战:看 App 的编译状态)
  • [十一、实战:dex2oat 调优](#十一、实战:dex2oat 调优)
  • 十二、常见踩坑记录
  • 十三、总结

一、ART 之前:Dalvik 为什么被换掉了

Android 4.4 以前用的虚拟机叫 Dalvik。Dalvik 是纯 JIT(Just-In-Time)编译器------App 每次启动,Dalvik 把 DEX 字节码一条一条解释成机器码执行。每次打开都要重新翻译一次,启动慢,费 CPU。

ART(Android Runtime)在 4.4 作为实验开关引入,5.0 正式替换 Dalvik。核心变化:引入 AOT(Ahead-Of-Time)编译------App 安装时就预先把 DEX 编译好。
#mermaid-svg-mXT4mNIjBaD5x9hj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mXT4mNIjBaD5x9hj .error-icon{fill:#552222;}#mermaid-svg-mXT4mNIjBaD5x9hj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mXT4mNIjBaD5x9hj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mXT4mNIjBaD5x9hj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mXT4mNIjBaD5x9hj .marker.cross{stroke:#333333;}#mermaid-svg-mXT4mNIjBaD5x9hj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mXT4mNIjBaD5x9hj p{margin:0;}#mermaid-svg-mXT4mNIjBaD5x9hj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj .cluster-label text{fill:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj .cluster-label span{color:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj .cluster-label span p{background-color:transparent;}#mermaid-svg-mXT4mNIjBaD5x9hj .label text,#mermaid-svg-mXT4mNIjBaD5x9hj span{fill:#333;color:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj .node rect,#mermaid-svg-mXT4mNIjBaD5x9hj .node circle,#mermaid-svg-mXT4mNIjBaD5x9hj .node ellipse,#mermaid-svg-mXT4mNIjBaD5x9hj .node polygon,#mermaid-svg-mXT4mNIjBaD5x9hj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mXT4mNIjBaD5x9hj .rough-node .label text,#mermaid-svg-mXT4mNIjBaD5x9hj .node .label text,#mermaid-svg-mXT4mNIjBaD5x9hj .image-shape .label,#mermaid-svg-mXT4mNIjBaD5x9hj .icon-shape .label{text-anchor:middle;}#mermaid-svg-mXT4mNIjBaD5x9hj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mXT4mNIjBaD5x9hj .rough-node .label,#mermaid-svg-mXT4mNIjBaD5x9hj .node .label,#mermaid-svg-mXT4mNIjBaD5x9hj .image-shape .label,#mermaid-svg-mXT4mNIjBaD5x9hj .icon-shape .label{text-align:center;}#mermaid-svg-mXT4mNIjBaD5x9hj .node.clickable{cursor:pointer;}#mermaid-svg-mXT4mNIjBaD5x9hj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mXT4mNIjBaD5x9hj .arrowheadPath{fill:#333333;}#mermaid-svg-mXT4mNIjBaD5x9hj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mXT4mNIjBaD5x9hj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mXT4mNIjBaD5x9hj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mXT4mNIjBaD5x9hj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mXT4mNIjBaD5x9hj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mXT4mNIjBaD5x9hj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mXT4mNIjBaD5x9hj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mXT4mNIjBaD5x9hj .cluster text{fill:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj .cluster span{color:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mXT4mNIjBaD5x9hj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mXT4mNIjBaD5x9hj rect.text{fill:none;stroke-width:0;}#mermaid-svg-mXT4mNIjBaD5x9hj .icon-shape,#mermaid-svg-mXT4mNIjBaD5x9hj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mXT4mNIjBaD5x9hj .icon-shape p,#mermaid-svg-mXT4mNIjBaD5x9hj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mXT4mNIjBaD5x9hj .icon-shape .label rect,#mermaid-svg-mXT4mNIjBaD5x9hj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mXT4mNIjBaD5x9hj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mXT4mNIjBaD5x9hj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mXT4mNIjBaD5x9hj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ART 混合 (7.0+)
DEX
安装: 轻量 AOT
运行: JIT 补热点
空闲: 后台 AOT 重编译
ART (5.0)
DEX 字节码
dex2oat 安装时预编译
机器码 oat 文件

启动直接执行
Dalvik
DEX 字节码
JIT 运行时逐条翻译
机器码

每次启动重复翻译

Dalvik vs ART 一表对比:

Dalvik ART 5.0 ART 7.0+
编译时机 运行时 JIT 安装时 AOT 全量 安装时轻量 + 运行时 JIT + 后台 AOT
App 安装速度 慢(全量编译) 较快
首次启动速度
编译产物空间 中等
GC 暂停 两次 STW 一次 STW 并发,几乎无感

二、ART 的三种编译模式

从 Android 7.0 开始,ART 默认走混合编译。dex2oat 根据**编译策略(compiler-filter)**决定怎么处理 DEX:
#mermaid-svg-LNPl8Pw7UVqAzlZ9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .error-icon{fill:#552222;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .marker.cross{stroke:#333333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 p{margin:0;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .cluster-label text{fill:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .cluster-label span{color:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .cluster-label span p{background-color:transparent;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .label text,#mermaid-svg-LNPl8Pw7UVqAzlZ9 span{fill:#333;color:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node rect,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node circle,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node ellipse,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node polygon,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .rough-node .label text,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node .label text,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .image-shape .label,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .rough-node .label,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node .label,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .image-shape .label,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .icon-shape .label{text-align:center;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node.clickable{cursor:pointer;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .arrowheadPath{fill:#333333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .cluster text{fill:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .cluster span{color:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .icon-shape,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .icon-shape p,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .icon-shape .label rect,#mermaid-svg-LNPl8Pw7UVqAzlZ9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LNPl8Pw7UVqAzlZ9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} speed

全量 AOT
speed-profile

按 profile 编译
verify

只验证不编译
APK 安装
dex2oat 读取 compiler-filter
编译策略
全部 DEX 编译成机器码

空间最大

启动最快
只编译 profile 里的热点方法

空间适中

启动快
不做 AOT

纯解释 + JIT

空间最小

启动慢

三种策略一句话:

策略 空间 启动 什么时候用
speed 最大 最快 系统 jar、Boot Image
speed-profile 中等 普通 App(默认)
verify 最小 极少用,debug 包

三、AOT 编译:dex2oat 怎么把 DEX 变成机器码

dex2oat 是 ART 的预编译器。App 安装时由 installd 进程调起,输入 DEX,输出三种产物。
#mermaid-svg-8BbFswefCrWaKAGe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8BbFswefCrWaKAGe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8BbFswefCrWaKAGe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8BbFswefCrWaKAGe .error-icon{fill:#552222;}#mermaid-svg-8BbFswefCrWaKAGe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8BbFswefCrWaKAGe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8BbFswefCrWaKAGe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8BbFswefCrWaKAGe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8BbFswefCrWaKAGe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8BbFswefCrWaKAGe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8BbFswefCrWaKAGe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8BbFswefCrWaKAGe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8BbFswefCrWaKAGe .marker.cross{stroke:#333333;}#mermaid-svg-8BbFswefCrWaKAGe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8BbFswefCrWaKAGe p{margin:0;}#mermaid-svg-8BbFswefCrWaKAGe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8BbFswefCrWaKAGe .cluster-label text{fill:#333;}#mermaid-svg-8BbFswefCrWaKAGe .cluster-label span{color:#333;}#mermaid-svg-8BbFswefCrWaKAGe .cluster-label span p{background-color:transparent;}#mermaid-svg-8BbFswefCrWaKAGe .label text,#mermaid-svg-8BbFswefCrWaKAGe span{fill:#333;color:#333;}#mermaid-svg-8BbFswefCrWaKAGe .node rect,#mermaid-svg-8BbFswefCrWaKAGe .node circle,#mermaid-svg-8BbFswefCrWaKAGe .node ellipse,#mermaid-svg-8BbFswefCrWaKAGe .node polygon,#mermaid-svg-8BbFswefCrWaKAGe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8BbFswefCrWaKAGe .rough-node .label text,#mermaid-svg-8BbFswefCrWaKAGe .node .label text,#mermaid-svg-8BbFswefCrWaKAGe .image-shape .label,#mermaid-svg-8BbFswefCrWaKAGe .icon-shape .label{text-anchor:middle;}#mermaid-svg-8BbFswefCrWaKAGe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8BbFswefCrWaKAGe .rough-node .label,#mermaid-svg-8BbFswefCrWaKAGe .node .label,#mermaid-svg-8BbFswefCrWaKAGe .image-shape .label,#mermaid-svg-8BbFswefCrWaKAGe .icon-shape .label{text-align:center;}#mermaid-svg-8BbFswefCrWaKAGe .node.clickable{cursor:pointer;}#mermaid-svg-8BbFswefCrWaKAGe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8BbFswefCrWaKAGe .arrowheadPath{fill:#333333;}#mermaid-svg-8BbFswefCrWaKAGe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8BbFswefCrWaKAGe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8BbFswefCrWaKAGe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8BbFswefCrWaKAGe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8BbFswefCrWaKAGe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8BbFswefCrWaKAGe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8BbFswefCrWaKAGe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8BbFswefCrWaKAGe .cluster text{fill:#333;}#mermaid-svg-8BbFswefCrWaKAGe .cluster span{color:#333;}#mermaid-svg-8BbFswefCrWaKAGe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8BbFswefCrWaKAGe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8BbFswefCrWaKAGe rect.text{fill:none;stroke-width:0;}#mermaid-svg-8BbFswefCrWaKAGe .icon-shape,#mermaid-svg-8BbFswefCrWaKAGe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8BbFswefCrWaKAGe .icon-shape p,#mermaid-svg-8BbFswefCrWaKAGe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8BbFswefCrWaKAGe .icon-shape .label rect,#mermaid-svg-8BbFswefCrWaKAGe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8BbFswefCrWaKAGe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8BbFswefCrWaKAGe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8BbFswefCrWaKAGe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} APK 安装触发
installd
★ 调起 dex2oat
读 .apk → classes.dex
读 boot.art

系统类预编译产物
dex2oat 编译过程
输出 .vdex

DEX 快速校验版
输出 .odex

编译好的机器码
输出 .art

类预初始化快照

真实 dex2oat 调用长这样:

bash 复制代码
dex2oat
  --dex-file=/data/app/com.example.app-xxx/base.apk
  --oat-file=/data/app/com.example.app-xxx/oat/arm64/base.odex
  --instruction-set=arm64
  --compiler-filter=speed-profile
  --app-image-file=/data/app/com.example.app-xxx/oat/arm64/base.art
  --profile-file=/data/misc/profiles/ref/com.example.app/primary.prof

关键参数解读:

参数 含义
--dex-file 输入:要编译的 DEX
--oat-file 输出:.odex 文件
--instruction-set 目标 CPU(arm64 / x86_64)
--compiler-filter 编译策略
--app-image-file 输出:.art 快照
--profile-file 输入:profile 热点记录

四、JIT 编译:运行时热点优化

AOT 不是万能的。安装时只能猜哪些方法会频繁调用------猜不准。所以 ART 保留了 JIT,在运行时检测热点并当场编译。
#mermaid-svg-CBW7qXC3B6iJZO47{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CBW7qXC3B6iJZO47 .error-icon{fill:#552222;}#mermaid-svg-CBW7qXC3B6iJZO47 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CBW7qXC3B6iJZO47 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CBW7qXC3B6iJZO47 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CBW7qXC3B6iJZO47 .marker.cross{stroke:#333333;}#mermaid-svg-CBW7qXC3B6iJZO47 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CBW7qXC3B6iJZO47 p{margin:0;}#mermaid-svg-CBW7qXC3B6iJZO47 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 .cluster-label text{fill:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 .cluster-label span{color:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 .cluster-label span p{background-color:transparent;}#mermaid-svg-CBW7qXC3B6iJZO47 .label text,#mermaid-svg-CBW7qXC3B6iJZO47 span{fill:#333;color:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 .node rect,#mermaid-svg-CBW7qXC3B6iJZO47 .node circle,#mermaid-svg-CBW7qXC3B6iJZO47 .node ellipse,#mermaid-svg-CBW7qXC3B6iJZO47 .node polygon,#mermaid-svg-CBW7qXC3B6iJZO47 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CBW7qXC3B6iJZO47 .rough-node .label text,#mermaid-svg-CBW7qXC3B6iJZO47 .node .label text,#mermaid-svg-CBW7qXC3B6iJZO47 .image-shape .label,#mermaid-svg-CBW7qXC3B6iJZO47 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CBW7qXC3B6iJZO47 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CBW7qXC3B6iJZO47 .rough-node .label,#mermaid-svg-CBW7qXC3B6iJZO47 .node .label,#mermaid-svg-CBW7qXC3B6iJZO47 .image-shape .label,#mermaid-svg-CBW7qXC3B6iJZO47 .icon-shape .label{text-align:center;}#mermaid-svg-CBW7qXC3B6iJZO47 .node.clickable{cursor:pointer;}#mermaid-svg-CBW7qXC3B6iJZO47 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CBW7qXC3B6iJZO47 .arrowheadPath{fill:#333333;}#mermaid-svg-CBW7qXC3B6iJZO47 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CBW7qXC3B6iJZO47 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CBW7qXC3B6iJZO47 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CBW7qXC3B6iJZO47 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CBW7qXC3B6iJZO47 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CBW7qXC3B6iJZO47 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CBW7qXC3B6iJZO47 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CBW7qXC3B6iJZO47 .cluster text{fill:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 .cluster span{color:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CBW7qXC3B6iJZO47 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CBW7qXC3B6iJZO47 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CBW7qXC3B6iJZO47 .icon-shape,#mermaid-svg-CBW7qXC3B6iJZO47 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CBW7qXC3B6iJZO47 .icon-shape p,#mermaid-svg-CBW7qXC3B6iJZO47 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CBW7qXC3B6iJZO47 .icon-shape .label rect,#mermaid-svg-CBW7qXC3B6iJZO47 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CBW7qXC3B6iJZO47 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CBW7qXC3B6iJZO47 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CBW7qXC3B6iJZO47 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 没到阈值
到了 变热点

方法首次执行

走解释器
被调了 N 次?
★ JIT 编译线程

把该方法编译成机器码
机器码写入

JIT Code Cache
后续调用

直接跑机器码
Profile 记录:

这个方法很热?
写入 profile 文件
后台 dex2oat

读取 profile

重新 AOT 持久化

profile 文件是 JIT 的"记忆"。路径:/data/misc/profiles/ref/<包名>/primary.prof


五、混合编译:AOT + JIT 一起干活的全周期

Android 7.0+ 的完整编译循环:
#mermaid-svg-pPWH3NOPyqyOByTT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pPWH3NOPyqyOByTT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pPWH3NOPyqyOByTT .error-icon{fill:#552222;}#mermaid-svg-pPWH3NOPyqyOByTT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pPWH3NOPyqyOByTT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pPWH3NOPyqyOByTT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pPWH3NOPyqyOByTT .marker.cross{stroke:#333333;}#mermaid-svg-pPWH3NOPyqyOByTT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pPWH3NOPyqyOByTT p{margin:0;}#mermaid-svg-pPWH3NOPyqyOByTT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pPWH3NOPyqyOByTT .cluster-label text{fill:#333;}#mermaid-svg-pPWH3NOPyqyOByTT .cluster-label span{color:#333;}#mermaid-svg-pPWH3NOPyqyOByTT .cluster-label span p{background-color:transparent;}#mermaid-svg-pPWH3NOPyqyOByTT .label text,#mermaid-svg-pPWH3NOPyqyOByTT span{fill:#333;color:#333;}#mermaid-svg-pPWH3NOPyqyOByTT .node rect,#mermaid-svg-pPWH3NOPyqyOByTT .node circle,#mermaid-svg-pPWH3NOPyqyOByTT .node ellipse,#mermaid-svg-pPWH3NOPyqyOByTT .node polygon,#mermaid-svg-pPWH3NOPyqyOByTT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pPWH3NOPyqyOByTT .rough-node .label text,#mermaid-svg-pPWH3NOPyqyOByTT .node .label text,#mermaid-svg-pPWH3NOPyqyOByTT .image-shape .label,#mermaid-svg-pPWH3NOPyqyOByTT .icon-shape .label{text-anchor:middle;}#mermaid-svg-pPWH3NOPyqyOByTT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pPWH3NOPyqyOByTT .rough-node .label,#mermaid-svg-pPWH3NOPyqyOByTT .node .label,#mermaid-svg-pPWH3NOPyqyOByTT .image-shape .label,#mermaid-svg-pPWH3NOPyqyOByTT .icon-shape .label{text-align:center;}#mermaid-svg-pPWH3NOPyqyOByTT .node.clickable{cursor:pointer;}#mermaid-svg-pPWH3NOPyqyOByTT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pPWH3NOPyqyOByTT .arrowheadPath{fill:#333333;}#mermaid-svg-pPWH3NOPyqyOByTT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pPWH3NOPyqyOByTT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pPWH3NOPyqyOByTT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pPWH3NOPyqyOByTT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pPWH3NOPyqyOByTT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pPWH3NOPyqyOByTT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pPWH3NOPyqyOByTT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pPWH3NOPyqyOByTT .cluster text{fill:#333;}#mermaid-svg-pPWH3NOPyqyOByTT .cluster span{color:#333;}#mermaid-svg-pPWH3NOPyqyOByTT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pPWH3NOPyqyOByTT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pPWH3NOPyqyOByTT rect.text{fill:none;stroke-width:0;}#mermaid-svg-pPWH3NOPyqyOByTT .icon-shape,#mermaid-svg-pPWH3NOPyqyOByTT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pPWH3NOPyqyOByTT .icon-shape p,#mermaid-svg-pPWH3NOPyqyOByTT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pPWH3NOPyqyOByTT .icon-shape .label rect,#mermaid-svg-pPWH3NOPyqyOByTT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pPWH3NOPyqyOByTT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pPWH3NOPyqyOByTT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pPWH3NOPyqyOByTT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 首次安装
dex2oat speed-profile
用户打开 App
解释执行 + AOT 机器码混着跑
热点方法触发 JIT
JIT 编译 → 写入 Code Cache
记录热点到 profile
手机空闲 + 充电
dex2oat 读取 profile

重新 AOT 编译热点
下次启动

★ 更快的机器码已就位

App 越用越流畅不是玄学------JIT 在后台不断学习,profile 越积累越精确,AOT 编译的命中率越高。


六、ART 怎么加载一个类

从 DEX 到内存中可用的 Class:
#mermaid-svg-Pgs4U9xsqZLhB1zG{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Pgs4U9xsqZLhB1zG .error-icon{fill:#552222;}#mermaid-svg-Pgs4U9xsqZLhB1zG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Pgs4U9xsqZLhB1zG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .marker.cross{stroke:#333333;}#mermaid-svg-Pgs4U9xsqZLhB1zG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Pgs4U9xsqZLhB1zG p{margin:0;}#mermaid-svg-Pgs4U9xsqZLhB1zG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .cluster-label text{fill:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .cluster-label span{color:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .cluster-label span p{background-color:transparent;}#mermaid-svg-Pgs4U9xsqZLhB1zG .label text,#mermaid-svg-Pgs4U9xsqZLhB1zG span{fill:#333;color:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .node rect,#mermaid-svg-Pgs4U9xsqZLhB1zG .node circle,#mermaid-svg-Pgs4U9xsqZLhB1zG .node ellipse,#mermaid-svg-Pgs4U9xsqZLhB1zG .node polygon,#mermaid-svg-Pgs4U9xsqZLhB1zG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .rough-node .label text,#mermaid-svg-Pgs4U9xsqZLhB1zG .node .label text,#mermaid-svg-Pgs4U9xsqZLhB1zG .image-shape .label,#mermaid-svg-Pgs4U9xsqZLhB1zG .icon-shape .label{text-anchor:middle;}#mermaid-svg-Pgs4U9xsqZLhB1zG .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .rough-node .label,#mermaid-svg-Pgs4U9xsqZLhB1zG .node .label,#mermaid-svg-Pgs4U9xsqZLhB1zG .image-shape .label,#mermaid-svg-Pgs4U9xsqZLhB1zG .icon-shape .label{text-align:center;}#mermaid-svg-Pgs4U9xsqZLhB1zG .node.clickable{cursor:pointer;}#mermaid-svg-Pgs4U9xsqZLhB1zG .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .arrowheadPath{fill:#333333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Pgs4U9xsqZLhB1zG .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Pgs4U9xsqZLhB1zG .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Pgs4U9xsqZLhB1zG .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Pgs4U9xsqZLhB1zG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .cluster text{fill:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG .cluster span{color:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Pgs4U9xsqZLhB1zG .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Pgs4U9xsqZLhB1zG rect.text{fill:none;stroke-width:0;}#mermaid-svg-Pgs4U9xsqZLhB1zG .icon-shape,#mermaid-svg-Pgs4U9xsqZLhB1zG .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Pgs4U9xsqZLhB1zG .icon-shape p,#mermaid-svg-Pgs4U9xsqZLhB1zG .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Pgs4U9xsqZLhB1zG .icon-shape .label rect,#mermaid-svg-Pgs4U9xsqZLhB1zG .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Pgs4U9xsqZLhB1zG .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Pgs4U9xsqZLhB1zG .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Pgs4U9xsqZLhB1zG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 加载过
没加载
没有
已加载
ClassLoader.loadClass()
class_table 里

已经加载过?
直接返回
从 DEX 读 ClassDef
解析字段 / 方法 / 接口
父类加载了没?
★ 递归加载父类
分配 Class 对象
Link:分配静态字段

计算方法偏移
Initialize:执行 static 代码块
类可用

源码对应(ART 内部):

cpp 复制代码
// art/runtime/class_linker.cc
ClassLinker::DefineClass(...)
  → LoadClass()       // 从 DEX 解析
  → LinkClass()       // 分配字段、计算偏移
  → InitializeClass() // 执行 static{}

七、一个方法在 ART 里的执行路径

ART 里有多种执行模式,从慢到快排:
#mermaid-svg-rkP33dteFMFRfJLk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rkP33dteFMFRfJLk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rkP33dteFMFRfJLk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rkP33dteFMFRfJLk .error-icon{fill:#552222;}#mermaid-svg-rkP33dteFMFRfJLk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rkP33dteFMFRfJLk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rkP33dteFMFRfJLk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rkP33dteFMFRfJLk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rkP33dteFMFRfJLk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rkP33dteFMFRfJLk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rkP33dteFMFRfJLk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rkP33dteFMFRfJLk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rkP33dteFMFRfJLk .marker.cross{stroke:#333333;}#mermaid-svg-rkP33dteFMFRfJLk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rkP33dteFMFRfJLk p{margin:0;}#mermaid-svg-rkP33dteFMFRfJLk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rkP33dteFMFRfJLk .cluster-label text{fill:#333;}#mermaid-svg-rkP33dteFMFRfJLk .cluster-label span{color:#333;}#mermaid-svg-rkP33dteFMFRfJLk .cluster-label span p{background-color:transparent;}#mermaid-svg-rkP33dteFMFRfJLk .label text,#mermaid-svg-rkP33dteFMFRfJLk span{fill:#333;color:#333;}#mermaid-svg-rkP33dteFMFRfJLk .node rect,#mermaid-svg-rkP33dteFMFRfJLk .node circle,#mermaid-svg-rkP33dteFMFRfJLk .node ellipse,#mermaid-svg-rkP33dteFMFRfJLk .node polygon,#mermaid-svg-rkP33dteFMFRfJLk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rkP33dteFMFRfJLk .rough-node .label text,#mermaid-svg-rkP33dteFMFRfJLk .node .label text,#mermaid-svg-rkP33dteFMFRfJLk .image-shape .label,#mermaid-svg-rkP33dteFMFRfJLk .icon-shape .label{text-anchor:middle;}#mermaid-svg-rkP33dteFMFRfJLk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rkP33dteFMFRfJLk .rough-node .label,#mermaid-svg-rkP33dteFMFRfJLk .node .label,#mermaid-svg-rkP33dteFMFRfJLk .image-shape .label,#mermaid-svg-rkP33dteFMFRfJLk .icon-shape .label{text-align:center;}#mermaid-svg-rkP33dteFMFRfJLk .node.clickable{cursor:pointer;}#mermaid-svg-rkP33dteFMFRfJLk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rkP33dteFMFRfJLk .arrowheadPath{fill:#333333;}#mermaid-svg-rkP33dteFMFRfJLk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rkP33dteFMFRfJLk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rkP33dteFMFRfJLk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rkP33dteFMFRfJLk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rkP33dteFMFRfJLk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rkP33dteFMFRfJLk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rkP33dteFMFRfJLk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rkP33dteFMFRfJLk .cluster text{fill:#333;}#mermaid-svg-rkP33dteFMFRfJLk .cluster span{color:#333;}#mermaid-svg-rkP33dteFMFRfJLk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rkP33dteFMFRfJLk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rkP33dteFMFRfJLk rect.text{fill:none;stroke-width:0;}#mermaid-svg-rkP33dteFMFRfJLk .icon-shape,#mermaid-svg-rkP33dteFMFRfJLk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rkP33dteFMFRfJLk .icon-shape p,#mermaid-svg-rkP33dteFMFRfJLk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rkP33dteFMFRfJLk .icon-shape .label rect,#mermaid-svg-rkP33dteFMFRfJLk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rkP33dteFMFRfJLk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rkP33dteFMFRfJLk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rkP33dteFMFRfJLk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是


没有

没有


调用 Java 方法
native?
直调 JNI
有 AOT 机器码?
★ 直接执行机器码

最快
JIT Code Cache 有?
从 Cache 取机器码执行
达到 JIT 阈值?
排队等 JIT

当前走解释器
★ 解释执行

逐条翻译

最慢

速度对比:

模式 速度 说明
解释执行 1x 基准,逐条翻译
JIT 编译 5x ~ 10x 运行时优化
AOT 编译 10x ~ 20x 安装时 / 后台优化

八、GC 垃圾回收

ART 的 GC 比 Dalvik 进化太多。Android 8.0 之后默认用 Concurrent Copying GC

ART GC 演进:

版本 GC 暂停
4.4 Dalvik CMS 两次 STW,卡顿明显
5.0 ~ 7.x CMS 改进 一次 STW
8.0+ Concurrent Copying 几乎无暂停

Concurrent Copying GC 思路:
#mermaid-svg-28WbLAjwv4bw2dZJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-28WbLAjwv4bw2dZJ .error-icon{fill:#552222;}#mermaid-svg-28WbLAjwv4bw2dZJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-28WbLAjwv4bw2dZJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-28WbLAjwv4bw2dZJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-28WbLAjwv4bw2dZJ .marker.cross{stroke:#333333;}#mermaid-svg-28WbLAjwv4bw2dZJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-28WbLAjwv4bw2dZJ p{margin:0;}#mermaid-svg-28WbLAjwv4bw2dZJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ .cluster-label text{fill:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ .cluster-label span{color:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ .cluster-label span p{background-color:transparent;}#mermaid-svg-28WbLAjwv4bw2dZJ .label text,#mermaid-svg-28WbLAjwv4bw2dZJ span{fill:#333;color:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ .node rect,#mermaid-svg-28WbLAjwv4bw2dZJ .node circle,#mermaid-svg-28WbLAjwv4bw2dZJ .node ellipse,#mermaid-svg-28WbLAjwv4bw2dZJ .node polygon,#mermaid-svg-28WbLAjwv4bw2dZJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-28WbLAjwv4bw2dZJ .rough-node .label text,#mermaid-svg-28WbLAjwv4bw2dZJ .node .label text,#mermaid-svg-28WbLAjwv4bw2dZJ .image-shape .label,#mermaid-svg-28WbLAjwv4bw2dZJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-28WbLAjwv4bw2dZJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-28WbLAjwv4bw2dZJ .rough-node .label,#mermaid-svg-28WbLAjwv4bw2dZJ .node .label,#mermaid-svg-28WbLAjwv4bw2dZJ .image-shape .label,#mermaid-svg-28WbLAjwv4bw2dZJ .icon-shape .label{text-align:center;}#mermaid-svg-28WbLAjwv4bw2dZJ .node.clickable{cursor:pointer;}#mermaid-svg-28WbLAjwv4bw2dZJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-28WbLAjwv4bw2dZJ .arrowheadPath{fill:#333333;}#mermaid-svg-28WbLAjwv4bw2dZJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-28WbLAjwv4bw2dZJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-28WbLAjwv4bw2dZJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-28WbLAjwv4bw2dZJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-28WbLAjwv4bw2dZJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-28WbLAjwv4bw2dZJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-28WbLAjwv4bw2dZJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-28WbLAjwv4bw2dZJ .cluster text{fill:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ .cluster span{color:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-28WbLAjwv4bw2dZJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-28WbLAjwv4bw2dZJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-28WbLAjwv4bw2dZJ .icon-shape,#mermaid-svg-28WbLAjwv4bw2dZJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-28WbLAjwv4bw2dZJ .icon-shape p,#mermaid-svg-28WbLAjwv4bw2dZJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-28WbLAjwv4bw2dZJ .icon-shape .label rect,#mermaid-svg-28WbLAjwv4bw2dZJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-28WbLAjwv4bw2dZJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-28WbLAjwv4bw2dZJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-28WbLAjwv4bw2dZJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} GC 触发
标记阶段:

找到所有活对象

并发,应用不暂停
短暂暂停

拿到完整的活对象列表
复制阶段:

把活对象拷到新空间

并发,应用继续跑
清理阶段:

旧空间整块回收
完成

Concurrent Copying 的精髓:不回收碎片了------直接把活对象搬到新地方,旧空间整片回收。没有碎片整理,就不需要 STW。


九、.vdex / .odex / .art 三种文件分别是干嘛的

bash 复制代码
/data/app/com.example.app-xxx/oat/arm64/
├── base.vdex     # DEX 快速校验文件
├── base.odex     # 编译好的机器码
└── base.art      # 类预初始化快照
文件 全称 干嘛用的
.vdex Verified DEX 安装时已验证过 DEX 完整性,下次直接跳过验证------加快加载
.odex Optimized DEX 把 DEX 编译成 CPU 的机器码------可以直接跑
.art ART Image 某些类在编译时就初始化好,启动时 mmap 到内存------连类加载都省了

不用 .art 和用了 .art 的区别:

复制代码
没用 .art:App 启动 → DEX → 验证 → 解析类 → 执行 static{} → 跑起来
用了 .art:App 启动 → mmap .art 到内存 → 直接跑起来(类已经在之前初始化好了)

十、实战:看 App 的编译状态

看 App 的 dexopt 信息:

bash 复制代码
adb shell dumpsys package com.example.app | grep -A 10 "Dexopt"
# 输出示例:
# primaryCpuAbi: arm64-v8a
# dexoptNeeded: 0
# dexoptFlags: 0

看编译后产物的文件大小:

bash 复制代码
adb shell ls -lh /data/app/com.example.app-*/oat/arm64/
# -rw-r--r-- 1 system system  4.2M base.vdex
# -rw-r--r-- 1 system system 12.3M base.odex
# -rw-r--r-- 1 system system  2.1M base.art

手动触发重新编译:

bash 复制代码
# 全量 AOT 编译(等于 speed,空间最大、最快)
adb shell cmd package compile -m speed -f com.example.app

# Profile 引导编译(默认策略)
adb shell cmd package compile -m speed-profile -f com.example.app

# 重置编译状态(删掉 oat 文件)
adb shell cmd package compile --reset com.example.app

看 profile 里记录了哪些方法:

bash 复制代码
adb shell pm dump-profiles com.example.app
# 输出每个方法的调用次数 / 是否热点

十一、实战:dex2oat 调优

场景一:App 启动慢,怀疑没做全量 AOT

bash 复制代码
# 看编译策略
adb shell dumpsys package com.example.app | grep compiler-filter
# 如果显示 verify,那就是没做 AOT

# 加全量编译
adb shell cmd package compile -m speed -f com.example.app
# 再测一次启动
adb shell am start -W com.example.app/.MainActivity

场景二:系统升级后第一次启动巨慢

系统 OTA 后,所有 App 的 oat 都失效了,需要重新 dex2oat。手机设置里显示"正在优化应用(1/120)"就是这个过程。

bash 复制代码
# 这是在干的事------对每个 App 跑一遍 dex2oat
# 如果用 -m speed,每个 App 都要跑几分钟
# 默认用 speed-profile,跑得较快

场景三:让 dex2oat 用更多线程加速

bash 复制代码
# 看 dex2oat 用了几个线程
adb logcat | grep dex2oat
# dex2oat I: Using 4 threads

# 改属性让 dex2oat 用更多线程(需要 root)
adb shell setprop dalvik.vm.dex2oat-threads 8
调优参数 默认 建议
dalvik.vm.dex2oat-threads 等于 CPU 核心数的一半 调成核心数,加快编译
dalvik.vm.dex2oat-filter speed-profile 预装 App 设 speed

场景四:减小 oat 空间占用

bash 复制代码
# 如果空间紧张,压缩 oat
adb shell cmd package compile -m space -f com.example.app

# 或者只对核心 App 用 speed,其余用 speed-profile

十二、常见踩坑记录

坑 1:debug 包比 release 包慢很多

Android Studio 直接 Run 装的 debug 包默认 compiler-filter 是 quickenverify,基本不做 AOT。release 包默认 speed-profile。所以 debug 包启动慢是正常的------不是你的代码问题。

坑 2:改了代码但 .odex 没更新

手动 push 新的 APK 但 oat 目录没重建------系统还是用旧的 .odex。

bash 复制代码
# 强制重新 dexopt
adb shell cmd package compile -m speed-profile -f com.example.app

# 或者直接删掉 oat 让系统重建
adb shell rm -rf /data/app/com.example.app-*/oat/
adb reboot

坑 3:混淆后 profile 失效

profile 记录的是混淆后的方法名。如果每次发版混淆规则变了------方法名全换了------上次积累的 profile 直接废。App 又得重新 JIT 收集。

对策:keep 规则里核心热路径类保持稳定,或者用 Baseline Profile 把热点预置进 APK。

坑 4:dex2oat 在开机时占满 CPU

手机刚开机,后台 dex2oat 编译几十个 App------CPU 占满、手机发烫。

bash 复制代码
# 看当前 dex2oat 在跑哪些编译
adb shell pgrep dex2oat
adb shell cat /proc/$(pidof dex2oat)/cmdline

任务列表里有 bg-dexopt------这是系统在后台优化。尽量在充电+空闲时才触发。

坑 5:32 位设备上 .art 太大导致 OOM

超大 App 的 .art 文件 mmap 到 32 位虚拟地址空间(总共才 3GB+ 多),可能直接 mmap 失败。

bash 复制代码
# 看 .art 多大
adb shell ls -lh /data/app/com.example.app-*/oat/arm/base.art
# 如果 150MB+,考虑砍一下预初始化的类

十三、总结

ART 完整流程图:
#mermaid-svg-L3ZyBFPaXyImsuOz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-L3ZyBFPaXyImsuOz .error-icon{fill:#552222;}#mermaid-svg-L3ZyBFPaXyImsuOz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-L3ZyBFPaXyImsuOz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-L3ZyBFPaXyImsuOz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-L3ZyBFPaXyImsuOz .marker.cross{stroke:#333333;}#mermaid-svg-L3ZyBFPaXyImsuOz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-L3ZyBFPaXyImsuOz p{margin:0;}#mermaid-svg-L3ZyBFPaXyImsuOz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz .cluster-label text{fill:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz .cluster-label span{color:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz .cluster-label span p{background-color:transparent;}#mermaid-svg-L3ZyBFPaXyImsuOz .label text,#mermaid-svg-L3ZyBFPaXyImsuOz span{fill:#333;color:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz .node rect,#mermaid-svg-L3ZyBFPaXyImsuOz .node circle,#mermaid-svg-L3ZyBFPaXyImsuOz .node ellipse,#mermaid-svg-L3ZyBFPaXyImsuOz .node polygon,#mermaid-svg-L3ZyBFPaXyImsuOz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-L3ZyBFPaXyImsuOz .rough-node .label text,#mermaid-svg-L3ZyBFPaXyImsuOz .node .label text,#mermaid-svg-L3ZyBFPaXyImsuOz .image-shape .label,#mermaid-svg-L3ZyBFPaXyImsuOz .icon-shape .label{text-anchor:middle;}#mermaid-svg-L3ZyBFPaXyImsuOz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-L3ZyBFPaXyImsuOz .rough-node .label,#mermaid-svg-L3ZyBFPaXyImsuOz .node .label,#mermaid-svg-L3ZyBFPaXyImsuOz .image-shape .label,#mermaid-svg-L3ZyBFPaXyImsuOz .icon-shape .label{text-align:center;}#mermaid-svg-L3ZyBFPaXyImsuOz .node.clickable{cursor:pointer;}#mermaid-svg-L3ZyBFPaXyImsuOz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-L3ZyBFPaXyImsuOz .arrowheadPath{fill:#333333;}#mermaid-svg-L3ZyBFPaXyImsuOz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-L3ZyBFPaXyImsuOz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-L3ZyBFPaXyImsuOz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-L3ZyBFPaXyImsuOz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-L3ZyBFPaXyImsuOz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-L3ZyBFPaXyImsuOz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-L3ZyBFPaXyImsuOz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-L3ZyBFPaXyImsuOz .cluster text{fill:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz .cluster span{color:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-L3ZyBFPaXyImsuOz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-L3ZyBFPaXyImsuOz rect.text{fill:none;stroke-width:0;}#mermaid-svg-L3ZyBFPaXyImsuOz .icon-shape,#mermaid-svg-L3ZyBFPaXyImsuOz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-L3ZyBFPaXyImsuOz .icon-shape p,#mermaid-svg-L3ZyBFPaXyImsuOz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-L3ZyBFPaXyImsuOz .icon-shape .label rect,#mermaid-svg-L3ZyBFPaXyImsuOz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-L3ZyBFPaXyImsuOz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-L3ZyBFPaXyImsuOz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-L3ZyBFPaXyImsuOz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 运行时
安装时

APK 安装
dex2oat
.vdex 校验文件
.odex 机器码
.art 预初始化快照
App 启动
mmap .art 跳过类加载
跑 .odex 机器码
热点?
JIT 编译
写 profile
后台 AOT 重编译

三种文件一句话速记:

文件 一句话
.vdex 跳过 DEX 验证
.odex 机器码,直接执行
.art 类预初始化,mmap 秒加载

核心命令速查:

你要什么 命令
看编译状态 `dumpsys package
全量编译 cmd package compile -m speed -f <pkg>
Profile 编译 cmd package compile -m speed-profile -f <pkg>
重置编译 cmd package compile --reset <pkg>
看 profile pm dump-profiles <pkg>
看产物大小 ls -lh /data/app/<pkg>-*/oat/

一句话总结: ART 在安装时用 dex2oat 把 DEX 编译成机器码(.odex)和初始化快照(.art),启动时 mmap 直接跑。运行中 JIT 检测热点并记录到 profile,后台空闲时重新 AOT 持久化。App 越用越流畅是真的------profile 积累越多,AOT 命中率越高。

相关推荐
万能小林子1 小时前
如何将网页在线转APP?5种打包工具对比速成指南(含在线/手机/电脑方案)
android·ios·uni-app·web app·wap2app·app打包·app封装
梅塔鲁1 小时前
Kotlin成安卓开发首选
android
zhangphil1 小时前
Android Coil 3 extend ImageRequest‘s custom method/function,Kotlin(2)
android·kotlin
诸神黄昏EX1 小时前
Android 性能优化【篇五:应用启动分析流程】
android
执念、坚持1 小时前
解决 vscode 中导入 android aosp 源码卡顿问题
android·ide·vscode
码云骑士1 小时前
Android ADB常用命令
android·adb
Kapaseker1 小时前
五分钟搞定 Compose 用户名密码自动填充
android·kotlin
EasyCVR2 小时前
监控“孤岛”困局:国标GB28181视频监控平台EasyCVR一站式视频融合平台实现视频系统统一管理
android·音视频
眸生2 小时前
基于NeteaseCloudMusicApi的音乐app 支持 DeepSeek 自然语言找歌、批量导入歌单、下载音乐转换成MP3,下载歌词
android·python·kotlin·android studio·音频·fastapi·android jetpack