Android虚拟机内存模型

1 JVM内存模型

JVM内存模型可以分为两个部分,如下图所示,堆和方法区是所有线程共有的,而虚拟机栈,本地方法栈和程序计数器则是线程私有的。

堆(Heap)


在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old ),新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,该内存区域存放了对象实例及数组(但不是所有的对象实例都在堆中)。

方法区(Method Area)


存放从class文件里加载进来的类的,而且常量池也是在这块区域内的。与Java堆一样,是各个线程共享的内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。

虚拟机栈(JVM Stack)


每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用。
虚拟机栈的作用:主管Java程序的运行,它保存方法的局部变量、部分结果,并参与方法的调用和返回。

每个线程运行时都会创建自己的线程栈,用于存放栈帧。
栈帧中存储了局部变量表、操作数栈、动态链接信息以及方法返回地址等信息。每个方法被执行的时候都会创建一个”栈帧”,
每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

栈帧(Stack Frame) 是用于虚拟机执行时方法调用和方法执行时的数据结构,它是虚拟栈的基本元素,栈帧由局部变量区、操作数栈等组成,如下图所示:

本地方法栈(Native Stack)
与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。

程序计数器(PC Register)


在JVM的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了各条线程之间的切换后计数器能恢复到正确的执行位置,所以每条线程都会有一个独立的程序计数器。
当线程正在执行一个Java方法,程序计数器记录的是正在执行的JVM字节码指令的地址;如果正在执行的是一个Natvie(本地方法),那么这个计数器的值则为空(Underfined)。

2 ART虚拟机内存模型

ART作为Android的运行环境,同样采用了类似的内存区域划分,但在实现和优化上做了适合移动设备的调整:

堆区(Heap)


ART同样将内存管理的主要区域设为堆,用于存储所有的对象实例和数组。
堆的管理也依赖于垃圾回收机制,但ART使用了不同的GC算法,如CMS(并发标记清除)和GSS(分代垃圾收集)等,以减少应用的停顿时间。

方法区(Method Area)


在ART中,方法区的概念与JVM类似,用于存储类结构等信息。
ART没有使用元空间的概念,而是采用了一种线性分配的策略,以减少内存的碎片化。

栈区(Stack)


ART的栈区同样为每个线程提供私有空间,用于存放栈帧。
栈帧的结构和JVM类似,包含局部变量、操作数等信息。

直接内存(Direct Memory)


除了标准的JVM内存区域,Android还允许应用通过JNI直接分配和管理内存。这部分内存不受GC管理,需要开发者手动管理

2 虚拟机的实现方式有两种,基于栈的和基于寄存器的

基于栈的虚拟机,有JVM,CPython。基于寄存器的,有Dalvik,都要实现以下几点:

  1. 取指令,其中指令来源于内存
  2. 译码,决定指令类型(执行何种操作)。另外译码的过程要包括从内存中取操作数
  3. 执行。指令译码后,被虚拟机执行(其实最终都会借助于物理机资源)
  4. 存储计算结果

基于栈的虚拟机有一个操作数栈的概念

虚拟机在进行真正的运算时都是直接与操作数栈进行交互

好处就是虚拟机可以无视具体的物理架构,特别是寄存器。但缺点是速度慢,因为无论什么操作都要通过操作数栈这一结构。
执行时默认都是从操作数栈上取数据,那么就无需指定操作数
例如执行”a = b + c”,在基于栈的虚拟机上字节码指令如下所示:

I1: LOAD C
I2: LOAD B
I3: ADD
I4: STORE A

基于寄存器的虚拟机中没有操作数栈的概念,但是有很多虚拟寄存器

一般情况下这些寄存器(操作数)都是别名,需要执行引擎对这些寄存器(操作数)的解析,找出操作数的具体位置,然后取出操作数进行运算。

既然是虚拟寄存器,那么肯定不在CPU中,这些寄存器也存放在运行时栈中,本质上就是一个数组。

基于寄存器虚拟机执行该操作只有一条指令

I1: add a, b, c

“寄存器”的概念只是当前栈帧中一块连续的内存区域。这些数据在运算的时候,直接送入物理CPU进行计算,无需再传送到operand stack上然后再进行运算。

ART通过在安装时将应用编译成本地代码,避免了运行时的译码和指令分派过程

参考 https://www.cnblogs.com/hainange/p/6333995.html

  • 42
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值