Skip to content

本篇文章将讲述什么是栈,以及栈与堆的区别,将通过对比分析堆栈与变量、数组和对象之间的内在联系。

堆和变量的关系

如图所示变量的值都存与栈中,和堆并无关系。

堆和变量的关系.d

堆和数组的关系

观察如下代码,栈中存放变量,会将变量地址存放至栈中的局部变量表中,那么地址指向的就是堆,在堆中存放数组的数据。

什么是堆.drawio

注意看下面代码,当执行x=null时,x引用的内存地址被删除,那么x数组在堆中的值会被删除吗?答案是不会,堆中的0x0001任然被y引用,堆中的数据会一直存在,不会被垃圾回收算法删除。

java
public static void main(String[] args) {
    int[] x = new int[5];
    x[0] = 100;
    int[] y = x;
    x = null;
}

堆和对象的关系

如图所示,和数组类似,堆存储对象的值,栈存储的地址指向堆。

堆和对象的关系

如果book2指向book1,那么堆不会重新开辟空间,而是直接引用book1的空间

堆和对象的关系-重复引用.drawio

总结

栈:

  1. 基本数据类型、局部变量存放在栈帧内,方法执行完毕(栈帧出栈)立即释放,节约空间。
  2. 栈帧内的变量,没有默认值,需要手工设置。
  3. 栈帧只存留在单个线程中,其他线程访问不了。
  4. 可以使用-Xss来定义栈内存大小。
  5. 当堆栈内存已满时,Java运行时抛出java.lang.StackOverFlowError

堆:

  1. 数组和对象存于堆中,用完后(栈帧不再引用),靠垃圾回收算法清除。
  2. 堆内对象的变量都有默认值。
  3. 所有的线程共享堆,即所有栈帧的变量都能引用堆的内存地址。
  4. 可以使用-Xms和-Xmx的JVM选项来定义堆内存的启动大小和最大大小。
  5. 如果堆内存已满,则抛出java.lang.OutOfMemoryError: Java堆空间错误。