0%

Android - JVM虚拟机

JVM概述

Java程序的执行过程

一个java程序,首先经过javac编译成.class程序, 然后JVM将其加入到方法区,执行引擎会执行这些字节码。执行时,会翻译成操作系统的相关函数。JVM作为.class的翻译存在,输入字节码,调用操作系统的函数

过程:Java文件 -> 编译器 -> 字节码 -> JVM -> 机器码

JVM 全称 Java Virtual Machine, 也就是我们耳熟能详的 Java虚拟机。它能识别.class后缀的文件,并且能够解析它的指令,最终调用操作系统的函数,完成我们想要的操作。

字节码文件与JVM

  • 我们平时所说的Java字节码,指的是Java语言编译成的字节码,准确的说任何能在JVM平台上执行的字节码格式都是一样的,所以应该统称JVM字节码
  • 不同的编译器,可以编译出相同的字节码文件,字节码文件也可以在不同的JVM上运行
  • Java虚拟机与Java语言并没有直接联系,它只和特定二进制文件格式 .class 文件有所关联,CLASS文件中包含JVM虚拟机指令集(bytecodes)和符号表,还有一些其它的辅助信息

JVM跨语言性的设计思路

常见的虚拟机

Hotspot虚拟机

隶属于Sun,现阶段占据 JAVA语言虚拟机市场的绝对地位,一般所提到的虚拟机都是Hotspot虚拟机

Dalvik虚拟机 & ART虚拟机

Dalvik VM 隶属于 Google , 应用于 Android系统,并且在 Android2.2 中提供了 JIT

  • Dalvik是一款不是JVM的JVM虚拟机,本质上它没有遵循JVM规范
  • 不能直接运行java Class文件
  • 它的结构是基于寄存器结构,而不是JVM栈结构
  • 执行的是编译后的Dex文件,执行效率较高
  • 与Android 5.0后被ART替换

栈指令集架构和寄存器指令集架构

Java编译器指令流是基于栈指令集架构,而另一种指令集架构为基于寄存器的指令集架构

基于栈的指令集架构的特点:

  • 设计与实现简单,适用于资源受限系统
  • 避开寄存器的分配问题,使用0地址指令方式
  • 指令流中的指令操作过程基于栈,且位数小(8位),编译器容易实现
  • 不需要硬件支撑,可移植性好

基于寄存器的指令架构特点:

  • x86二进制指令集(区别于栈的8位,此处是16位):android中的Dalvik使用的是这种架构
  • 依赖于硬件,可移植性差
  • 性能优秀和执行更加高效
  • 花费更少的时间去执行一个操作
  • 基于寄存器架构的指令往往都以1~3地址指令为主,而基于栈省却地址指令操作,都基于栈完成

栈指令集:

JVM组成部分

运行时数据区

运行时数据区结构

堆栈在内存中的职责

栈是运行时的处理单位,而堆是运行时的存储单位

  • 栈是用来解决程序运行问题,如程序如何存放,如何去处理数据,方法是怎么执行

  • 堆是用来解决数据存储问题,数据放哪,怎么放

虚拟机栈基本信息

虚拟机栈是什么?

  • 承载方法调用过程中产生的数据容器,随线程开辟,为线程私有

作用:

  • 它主管java方法运行过程中所产生的值变量运算结果、方法的调用返回等信息管理

主核心:局部变量、计算结果

结构作用:

  • 栈结构的应用能产生一种快速有效的分配方案,访问速度仅次于程序计数器
  • Java直接堆栈操作只有两个:出栈、入栈
  • 这种应用不需要有GC设定

程序计数器/PC寄存器

栈区存储结构与运行原理

栈内部结构解析

局部变量表

局部变量表也被称为局部变量数组或者本地变量表

定义为一个数字数组,主要用于存储方法参数和定义方法体内的局部变量

由于局部变量表是建立在线程的栈上,是线程的私有数据,因此不存在数据安全问题

局部变量表所需要的容量大小是在编译器确定下来的,并保存在方法的code属性的maxinum local variables数据项中,运行期间局部变量表大小不变

方法嵌套调用的次数由栈的大小决定,局部变量表决定着栈帧的大小,这里是编译期就会确定下来

  • 默认在局部变量表第一位置入一个this指针
  • 参数也会置入
  • 内部所有声明的变量
  • 注意:32位: 1slot 引用类型32位
  • 大小在编译时固定

操作数栈

求大佬赏个饭