方法执行时的内存分配

JVM运行机制

  1. 方法只定义,不调用,是不会执行的,并且在JVM中也不会给该方法分配 “ 运行所属 ” 的内存空间。只有在调用这个方法的时候,才会动态的给这个方法分配所属的内存空间
  2. JVM中有三块主要的内存空间:
    1. 方法区内存【存储.class代码】
    2. 堆内存【存储 对象/实例】
    3. 栈内存【存储局部变量,方法执行区域】
  3. 关于 “ 栈 数据结构:
    1. 栈:Stack,是一种数据结构
    2. 数据结构反映的是数据的存储形态
    3. 数据结构是独立的学科
    4. 需要精通:数据结构 + 算法
    5. 常用的数据结构:数组、队列、栈、链表、二叉树、哈希表 / 散列表…
  4. 方法代码片段存在哪里?执行过程中的内存在哪里分配?
    1. 方法代码片属于.class字节码文件的一部分,字节码文件在类加载的时候,将其放到了方法区当中,所以JVM中的三块主要内存空间中方法区最先由数据,存放了代码片段
    2. 代码片段虽然在方法区内存当中只有一部分,但是可以被重复调用
  5. 方法在调用的瞬间,会给该方法分配内存空间,会在栈中发送压栈动作。方法执行结束之后,给该方法分配的内存空间全部释放,此时发送弹栈动作
    1. 压栈push:给方法分配内存
    2. 弹栈pop:释放该方法的内存空间
  6. 局部变量 在 “ 方法体 ” 中声明。运行阶段内存在栈中分配

在这里插入图片描述
在这里插入图片描述

代码运行时内存分配分析

详见原博客

以下程序在JVM中如何执行?

public class testMethod(){
  public static void main(String[] args){
    int a = 10;
    int b = 20;
    int retValue = sumInt(a, b);
    System.out.println("retValue = " + retValue);
  }
  
  public static int sumInt(int i, int j){
    int result = i + j;
    int num = 3;
    int retValue = divide(result, num);
    return retValue;
  }
  
  public static int divide(int x, int y){
    int z = x / y;
    return z;
  }
}

.java文件通过编译后,Class Loader(类加载器)将testMethod.class放到了方法区内存中。【方法区内存存放的是.class代码】

在这里插入图片描述

JVM 会默认执行入口函数main,代码执行时 JVM 在栈内存开辟一块空间供main执行。 JVM 将main放到了栈内存当中执行,期间发生了压栈(push)动作。栈帧永远指向栈顶元素,栈顶元素是活跃的。

在这里插入图片描述
代码一步一步执行后,逐渐为局部变量开辟内存空间。为main栈开辟了两个名为a、b的内存空间

在这里插入图片描述
当执行到第 5 行的时候也就是int retValue = sumInt(a, b);,调用了sumInt方法。调用的这一瞬间 JVM 又给sumInt开辟内存。而这时栈帧发生改变,指向了sumInt栈。由于栈帧改变,所以main已暂停执行、被阻塞,现在执行的是栈顶元素,由于栈帧永远指向的是栈顶元素,所以栈顶元素永远处于活跃状态。

在这里插入图片描述

main调用sumInt的时候,在参数传递的时候,实际上传递的是变量中保存的值。将ab变量的值给到sumInt而不是ab。所以sumInt无法操作main里面的局部变量【无法得到内存地址】。参数传递的时候是按顺序传递。

在这里插入图片描述
执行到第10行的时候int result = i + j;,这时候需要计算i + j的结果给result栈储存。而计算是由中央处理器也就是 CPU 来执行,CPU 将处理后的结果给到result

在这里插入图片描述
程序继续执行,当执行到第12行的时候int retValue = divide(result, num);,又调用 divide,JVM 给divide开辟了一块内存空间,发生了压栈动作。逐步开辟x、y、z栈,而z的结果需要通过 CPU 计算得到。

在这里插入图片描述
而程序遇到return语句后就会强制弹栈【释放内存空间】,继续栈顶元素的执行,这时候栈顶元素以及变成sumInt,弹栈后代表第12行int retValue = divide(result, num);结束。

在这里插入图片描述
divide的结果给到retValue

在这里插入图片描述

而往下走遇到return强制弹栈return retValue;sumInt弹栈之后代表着第5行int retValue = sumInt(a, b);结束。
在这里插入图片描述

往下走遇到了 System 类,这个类实际与其它 class (包含testMethod.class)一起被加载到代码区。调用 System类 里面的 println 方法后又压栈,执行完成后弹栈,最后main执行完成弹栈。资源全部释放。

在这里插入图片描述

理论

  1. 方法区存的是字节码 .class 代码
  2. 方法调用时,参数传递的时候,实际传递的是变量中保存的字面值,而不是变量本身
  3. 画图时,必须遵循 “ 方法自上而下的顺序依次执行 ” 这个原则
  4. 代码编译期不会执行任何计算,JVM执行时计算
  5. 栈结构遵循 先进后出,后进先出 的规则
  6. 栈内存主要存储的是局部变量
  7. 栈帧永远在栈顶,栈顶元素永远处于活跃状态,其他元素静止
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值