好的,我来给你一些例子来说明这些内存区域如何工作。¹²³

假设我们有以下的Java代码:

public class Test {
    public static int a = 10; //静态变量
    public static final int b = 20; //常量
 
    public static void main(String[] args) {
        int c = 30; //局部变量
        String d = "Hello"; //对象引用
        System.out.println(a + b + c + d);
    }
}

当我们运行这段代码时,JVM会在不同的内存区域进行以下操作:

  • 在方法区(method area)中,加载Test类的信息,包括类名、父类、接口、方法等。同时,在方法区中分配空间存储静态变量a和常量b的值。
  • 在堆(heap)中,创建一个String对象,存储”Hello”这个字符串,并分配一个内存地址。
  • 在栈(stack)中,为main方法创建一个栈帧(stack frame),用于存放局部变量c和对象引用d。c的值是30,d的值是String对象在堆中的内存地址。
  • 在栈帧中,执行main方法的字节码指令,调用System.out.println方法,并传递a + b + c + d作为参数。
  • 在栈(stack)中,为System.out.println方法创建一个新的栈帧(stack frame),用于存放参数和临时变量。参数是a + b + c + d的结果,即60Hello。
  • 在栈帧中,执行System.out.println方法的字节码指令,在控制台输出60Hello,并返回。
  • System.out.println方法执行完毕后,销毁其栈帧,并弹出栈(stack)。
  • main方法执行完毕后,销毁其栈帧,并弹出栈(stack)。
  • 程序结束后,JVM退出,释放所有内存资源。

你明白了吗?

好的,我来给你一些例子来说明这些内存区域如何工作。¹²³

假设我们有以下的Java代码:

public class Test {
    public static int a = 10; //静态变量
    public static final int b = 20; //常量
 
    public static void main(String[] args) {
        int c = 30; //局部变量
        String d = "Hello"; //对象引用
        System.out.println(a + b + c + d);
    }
}

当我们运行这段代码时,JVM会在不同的内存区域进行以下操作:

  • 在方法区(method area)中,加载Test类的信息,包括类名、父类、接口、方法等。同时,在方法区中分配空间存储静态变量a和常量b的值。
  • 在堆(heap)中,创建一个String对象,存储”Hello”这个字符串,并分配一个内存地址。
  • 在栈(stack)中,为main方法创建一个栈帧(stack frame),用于存放局部变量c和对象引用d。c的值是30,d的值是String对象在堆中的内存地址。
  • 在栈帧中,执行main方法的字节码指令,调用System.out.println方法,并传递a + b + c + d作为参数。
  • 在栈(stack)中,为System.out.println方法创建一个新的栈帧(stack frame),用于存放参数和临时变量。参数是a + b + c + d的结果,即60Hello。
  • 在栈帧中,执行System.out.println方法的字节码指令,在控制台输出60Hello,并返回。
  • System.out.println方法执行完毕后,销毁其栈帧,并弹出栈(stack)。
  • main方法执行完毕后,销毁其栈帧,并弹出栈(stack)。
  • 程序结束后,JVM退出,释放所有内存资源。

你明白了吗?

好的,我来给你一些例子来说明这些内存区域如何工作。¹²³

假设我们有以下的Java代码:

public class Test {
    public static int a = 10; //静态变量
    public static final int b = 20; //常量
 
    public static void main(String[] args) {
        int c = 30; //局部变量
        String d = "Hello"; //对象引用
        System.out.println(a + b + c + d);
    }
}

当我们运行这段代码时,JVM会在不同的内存区域进行以下操作:

  • 在方法区(method area)中,加载Test类的信息,包括类名、父类、接口、方法等。同时,在方法区中分配空间存储静态变量a和常量b的值。
  • 在堆(heap)中,创建一个String对象,存储”Hello”这个字符串,并分配一个内存地址。
  • 在栈(stack)中,为main方法创建一个栈帧(stack frame),用于存放局部变量c和对象引用d。c的值是30,d的值是String对象在堆中的内存地址。
  • 在栈帧中,执行main方法的字节码指令,调用System.out.println方法,并传递a + b + c + d作为参数。
  • 在栈(stack)中,为System.out.println方法创建一个新的栈帧(stack frame),用于存放参数和临时变量。参数是a + b + c + d的结果,即60Hello。
  • 在栈帧中,执行System.out.println方法的字节码指令,在控制台输出60Hello,并返回。
  • System.out.println方法执行完毕后,销毁其栈帧,并弹出栈(stack)。
  • main方法执行完毕后,销毁其栈帧,并弹出栈(stack)。
  • 程序结束后,JVM退出,释放所有内存资源。

你明白了吗?

好的,我再解释一下。你可以把栈(stack)想象成一叠盘子,每次调用一个方法就相当于放一个盘子在最上面,每次返回一个方法就相当于拿走最上面的盘子。栈(stack)中的数据是临时的,只在方法执行期间有效。你可以把堆(heap)想象成一个仓库,里面存放着各种对象,每个对象都有一个唯一的地址。堆(heap)中的数据是持久的,可以被多个方法共享和访问。你可以把方法区(method area)想象成一个图书馆,里面存放着各种类的信息和静态数据。方法区(method area)中的数据是全局的,可以被所有线程共享和访问

源: 与必应的对话, 2023/3/8(1) 详谈java虚拟机内存机制:栈(stack)、堆(heap)、方法区(method area) - 知乎. https://zhuanlan.zhihu.com/p/62903116 访问时间 2023/3/8. (2) 栈、堆、方法区 - 知乎. https://zhuanlan.zhihu.com/p/390851148 访问时间 2023/3/8. (3) 解释内存中的栈 (stack)、堆 (heap)和方法区 (method area)的用法。. https://blog.csdn.net/wu594914197/article/details/85256376 访问时间 2023/3/8.