Java 中的堆和栈是两种不同的内存分配方式。堆是动态分配内存的一种方式,其中对象在被创建时在堆内存中分配空间,并在不再需要时被自动释放。栈则是一种基于硬件支持的数据结构,其中数据按照 Last-In-First-Out(后进先出)的顺序进行处理。
在 Java 中,堆和栈都是放在 RAM(内存)中的。然而,它们在内存中的位置和处理方式是不同的。栈是一个固定区域,它会在 Java 程序启动时创建,并在程序执行结束时销毁。栈中存储的是基本类型数据和对象的引用。每当一个方法被调用时,JVM 会为这个方法分配一定的栈帧(Stack Frame),以存储方法的参数和局部变量等信息。当方法执行完毕时,栈帧会被弹出。因为栈是一个固定大小的区域,所以当栈中的空间被占满后,JVM 会抛出 StackOverflowError。
public static void main(String[] args) { int i = 0; try { recursiveMethod(); } catch (Throwable t) { System.out.println("i = " + i); t.printStackTrace(); } } private static void recursiveMethod() { int j = 0; recursiveMethod(); }
这段代码会一直递归执行recursiveMethod
方法,直到栈空间不足导致程序崩溃。
相比之下,堆是一个更为灵活的区域,它的大小取决于可用的内存。堆中存储的是对象、数组等数据结构。当我们使用new
操作符创建一个对象时,会在堆中分配一定的内存,并返回对象的引用。当对象不再被使用时,JVM 会使用垃圾回收器自动释放其在堆内存中所占用的空间。因为堆是一个可变大小的区域,所以当堆空间不足时,JVM 会抛出 OutOfMemoryError。
public static void main(String[] args) { List<Integer>list = new ArrayList<>(); while (true) { list.add(1); } }
这段代码会一直向list
中添加元素,直到堆空间不足导致程序崩溃。