JVM内存区域-栈的理解

来源:互联网 发布:万税 知乎 编辑:程序博客网 时间:2024/06/08 20:08

基本知识点

  • 栈 先进后出 LIFO的数据结构
  • 栈帧
    • 以线程为组,一个线程可能会创建多个栈帧
  • 栈帧的构成
    • 局部变量表
      • 编译期间确定其大小
      • 编译期间 存储在class文件的 该方法 对应的 方法表 的 CODE属性(表)中的 MAX_LOCAL属性中。
      • 如果方法是 实例方法,则局部变量表 第一个位置存储的是 this 引用
    • 操作数栈
      • 也是一个 LIFO的栈
      • 编译期间确定最大深度
      • 基本操作 就是将 局部变量表中的数据 根据class中的字节码指令不断地 入栈、出栈。
      • 单位:字宽, 一个字宽 代表32位的数据,可以存储java基本数据类型,包括double,long,他们占两个字宽。
    • 动态连接
      • 每个栈帧 都描述了一个方法,每个方法属于 一个 class文件,每个class拥有一个常量池,常量池中描述了很多 符号常量:比如 用户自定义的方法名,类名 等等。
      • 栈帧中 有一个引用,指向 被加载了的 class文件 (位于 java内存区域的 另外一个区域 :方法区中)中的 常量池。所谓动态连接,就是解析 当前栈帧中 出现的 符号引用(某个其他类的方法、或属性),将这个符号 引用变成 直接 引用的过程。
    • 方法返回地址
      • 方法退出 有两种方式
        • return 指令
        • 发生异常
      • 当遇到这两种情况时,结合程序计数器(一个线程私有的 内存区域 用于 记录 下一条 执行的字节码指令位于 class 中的地址。 ) 将当前 栈帧出栈,并切换到 下一个 栈帧。

通俗理解

  • 栈只是一个统称,其实我们真正需要了解的是栈帧。 栈帧是栈的基本结构,可以通俗的理解为,以线程为分组,一个线程每进入一个方法,就创建了一个栈帧,并将其压入栈中。

这里写图片描述

mainMethod(String args...){    T r1 = method1(arg1,arg2);    return r1; }

为了 方便理解 使用了 java 伪代码,其实 JVM执行的 是 编译后的 class 文件中的 字节码指令。

当一个线程进入到 mainMethod方法时,首先创建一个栈帧 并 将其入栈代表 mainMethod方法,逐行执行,发现调用method1时,保存好main栈帧的运行环境之后 创建新的栈帧代表 method1,然后将method1的栈帧入栈,通过method1的字节码指令,将位于栈帧中的局部变量表中 的arg1,arg2 ,依次压入 操作数栈, method1执行完毕后,通过method1栈帧记录的返回出口和程序计数器 查找到下一条 字节码指令,将计算结果 返回给 main 方法的,并将method1 栈帧 出栈,切换回 mainMethod的栈帧,并将计算结果 压入 mainMethod的 局部变量表的 r1变量中。

当然实际的情况远远比 这复杂的多,比如 栈帧之间 局部变量表 之间的共享等等,在这里只是做一个通俗的理解。

原创粉丝点击