本文概述
- 此为 Android 虚拟机与类加载机制 系列文章第一篇,文章从数据结构角度介绍了 Java虚拟机(基于栈)与android 虚拟机(基于寄存器),探究了其工作流程,重点介绍了android不同版本中虚拟机对程序的处理过程;
JVM与Dalvik:
- 示意图
基于栈的虚拟机
基于栈的虚拟机:JVM
- 线程对应栈,方法对应栈帧;
- Java 代码实质上是字符串,需要编译(javac)成字节码文件(.class)
- .class 文件是十六进制的东西
-
示意图:
字节码指令:
-
为什么要学字节码:为了字节码插桩
-
java 代码与对应的字节码文件:
- LINENUMBER 5 L0:调试信息,下面对应这一行Java代码对应的字节码指令
- 示意图:
-
字节码执行的过程:
基于寄存器的虚拟机
什么是寄存器:CPU中的存储单元(晶体管)
-
执行过程:
-
指令集指令到CPU指令:程序计数器为0,从指令集中拿到0号指令,交给CPU中的指令寄存器;
-
执行CPU指令:LOAD A,100
- 从内存地址为100处存储的变量,交给数据寄存器AX
-
重复这个过程即可
-
补充:ALU是算术逻辑单元
-
基于寄存器的虚拟机
-
重要部分:
-
流程是什么:模拟CPU中物理寄存器的流程,具体实现更难
-
没有操作数栈:
- 指令变少了
- 避免数据在数据变量与操作数栈的往复过程
- 虚拟寄存器:一块虚拟化(完成特定功能)的内存区域
- 虚拟机怎么回收:程序退出就回收了
- 方法同样对应着栈帧:栈帧里面将局部变量表与操作数栈合并了
-
Android 虚拟机
ART 与 Dalvik
-
Dalvik:执行dex字节码码,解释执行 + JIT,字节码需要翻译成机器码,才能在PC运行;
-
ART:5.0后 android 虚拟机,相当于Dalvik的升级版
-
直接跑机器码,但出来的APK仍然是字节码文件
-
ART执行的机器码是哪里来的?
- 从安装的时候就来了
-
-
重要概念:
- 解释执行:代码--->字节码
- JIT:运行过程中对热点代码进行编译或者优化
-
示意图:
dex2ot
-
Dalvik:在应用安装的时候,执行dexopt操作,将dex文件从APK 中提取出来变成一个odex文件
-
ART:在应用安装时(运行之前),使用dex2ot 工具将dex中的字节码编译成本地机器码
- 从android 5.0,6.0 是这样干的
- 优势:运行变快
- 缺点:安装变慢
-
示意图:
Android N 的运作方式
-
Android N(7.0及以上)
-
采用混编技术:
-
安装前:不再使用 AOT
-
运行时:JIT 热点编译(记录在Profile 文件中),Java代码解释执行
-
设备空闲时:读取 JIT 配置文件记录的热点代码,对其进行AOT,转成机器码(放在 .art,相当于缓存),下一次启动时,先看art 中有没有这样的类信息,有 ---> 将这些类对应的机器码放到classLoder中,这样classLoder就不用去 dex文件中找(找到后还要解释执行)
- 但 .art 中不一定有本次需要的类
-
-
-
问题:
-
Java 的代码就是类:
- JVM 需要拿到的是符合虚拟机规范的 .class 对象
-
配置文件(Profile)中保存的是什么
- 不是代码,是代码的信息
-
JIT 编译的代码的生命周期:
- 程序退出就没有了,仅对本次编译有效
- Dalvik的dex就是dex,而ART的odex是机器码
- 虚拟机有什么用:提供程序运行的环境
- zygote fork出来的是进程,进程去执行main方法,main中启动虚拟机
-
-
示意图: