Java堆内存和栈内存

JVM运行时数据区

jvm

  • 程序计数器:存放线程执行位置(main函数也是一个线程);
  • 虚拟机栈(栈内存):
    • 生命周期和对应的线程相同,存放该线程的局部变量、对象的引用;
    • 方法中可能嵌套调用别的方法,这些方法的变量以”先进后出、后进先出“的方式在栈内存中存储,所以内层方法无法访问外层方法的变量(他们在栈底),执行外层方法时内层方法的变量已经弹出栈消失了,所以外层方法也不会访问到内层方法的变量;
    • 一个方法的执行过程,就是这个方法对于帧栈的入栈出栈过程;
  • 本地方法栈:
    • 作用和虚拟机栈完全相同;
    • 虚拟机栈对应普通的java方法,本地方法栈对应native方法;
    • native方法是一个java调用非java代码的接口;
  • 方法区:
    • JVM内存管理中最大一块;
    • 存储常量(final修饰)、类变量/成员变量(static修饰)、类信息(每个类的访问控制符、修饰符、继承关系等);
  • 堆内存:JVM启动时创建,存放对象本身,不存放对对象的引用(引用存在栈内存);

堆内存和栈内存的区别

  • 变量存在栈内存中(无论是static类变量还是对象的变量),已经不在其作用域中的对象要及时弹出栈;
  • new出来的对象或实例,它的名称存在栈内存中,实体存在堆内存中,名称通过实体在堆内存的地址引用实体;
  • 垃圾回收的目标是堆内存中失去引用的对象实体;
  • 栈内存一般是用物理一级缓存实现,堆内存一般是用物理二级缓存实现,栈内存存取速度快于堆内存,代码本身存储在磁盘中,和堆栈内存无关;
  • 堆主要用来存放对象的,栈主要是用来执行程序的;
  • 每个线程有自己的栈内存(栈内存是线程私有的),在一个JVM实例中(一个java应用对应一个JVM实例),堆内存只有一个(堆内存是线程共享的);
  • 在java中:
    • 基本数据类型(int, short, long, byte, float, double, boolean, char),他们存储在栈内存中,函数调用它们的时候是”传值”;
    • 复杂数据类型(数组, 对象, map, List, Set等),他们的实体存储在堆内存中,栈内存中只存储他们的对象的名称、通过堆内存的地址引用实体对象,函数调用它们的时候是”传引用地址”;
您的支持是对我最大的鼓励!