JVM内存结构-栈

 hotsport  vm 是目前高性能虚拟的代表之一,采用解释器与及时编译器并存的架构。以下是JVM虚拟机的内存结构图。


 

 Java编译器将java文件编译成字节码文件  由类加载器将字节码文件加载到内存中:

 

        加载:获取一个类的字节流  将这个字节流代表的静态存储结构中转化为元数据区的运行时数据结构在内存中生一个代表这个类的Class对象,作为元数据区这个类的访问接口。

        链接
              验证:目的在于确保Class文件的字节流中包含的信息符号当前虚拟机的要求,保证被加载类的正确性,不会危害虚拟自身的安全。
      准备:为类变量分配内存不并且设置该类变量默认初始化值 即0。
      解析:将常量池中的符号引用转化为直接应用。

        初始化:初始化阶段就是类构造器方法clinit的过程。


以下是JVM运行简易架构图,主要分析运行时数据区。

  •  pc寄存器:JVM中的程序计数器用来存储执行下一条指令的地址,也就是将要执行的代码。



    pc寄存器是一块很小的内存空间,几乎可以忽略不计,也是一块运行速度很快的存储区域。每一个线程都有自己的程序计数器,是线程私有的,生命周期与线程的生命周期一致,程序计数器会存储当前线程正在执行 的java方法的JVM指令地址,如果执行的native方法则未指定值 undefined。它是唯一一个java虚拟机规范中没有规定 outofmemory 的区域。

     
  • java虚拟机栈:每一个线程在创建的时候都会创建一个虚拟机栈,其内部保存着一个个栈帧,对每一个java方法的调用。生命周期和线程一致。栈的操作只有来两个,每个方法执行进栈;
    执行结束出栈。对于栈来说不存在垃圾收集的问题,但是该区域有可能会OOM。

         栈帧内部结构每一个栈帧都存着局部变量表、操作数栈、动态链接、方法返回地址等

         局部变量表:也称本地变量表,局部变量表是建立在线程栈上的,是线程的私有数据因此不存在线程安全问题,局部变量表的容量大小是在编译期就确定的,在方法运行期间是不会改变局部变量表的大小的。

        操作数栈:每一个栈帧中除了局部变量表还包括一个后进先出的操作数栈,操作数栈在方法执行过程中根据字节码指令对栈进行入栈和出栈操作。

        动态链接:每一个栈帧内部都包含一个字指向运行时常量池中该栈帧所属的方法引用,包含这个引用的目的就是为了支持当前方的代码能够实现动态链接。java文件在编译成字节码时所有变量和方法引用都作为符号引用保存在class文件的常量池中,动态链接的作用就是将这些符号引用转换为直接引用。

         方法的返回地址:存放在该方法的pc寄存器中,有两种方式
                1、正常执行完成
                2、出现未处理的异常,非正常退出
无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址。而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。正常完成出口和异常完成出口的区别在于:通过异常完成出口退出的不会给他的上层调用者产生任何的返回值。

以下是程序在运行过程中 虚拟栈的变化过程。

  •  本地方法栈:在java虚拟机中的栈用于管理java方法的调用,本地方法栈用于管理本地方法的调用。本地方法是用C语言实现的,具体做法是Native Method Stack中登记的native方法在执行引擎执行时加载本地方法库。当某个线程调用了一个本地方法时,它便不受虚拟机控制且和虚拟机拥有同样的权限。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值