很多人都知道,JVM的内存空间划分为新生代,老年代,永久代,其中新生代和老年代的空间统称为堆区(heap),如图
还有一个概念是虚拟机栈(JVM Stack),是由栈桢(Stack Frame)组成的,栈桢内部有局部变量表和操作数栈,虚拟机栈属于线程私有内存空间,线程有pc计数器表示当前线程执行的位置.
这是运行时数据区的一张图片,显示了堆区和栈区:
但是虚拟机栈区和堆区之间的区别又是什么呢? 下面用一段示例程序阐明它们之间的关系:
1 |
|
下图表示这段代码中堆区和栈区内存分配
- 程序从main方法开始执行,虚拟机创建main方法的栈桢
- 之后执行第二行代码i=1这个变量是放在栈桢的局部变量表中的
- 之后执行第3行和第4行代码为对象分配内存空间,这个内存空间是在堆区进行分配的,栈桢中的局部变量表只是存储内存的引用地址
- 之后第5行代码调用foo()此时虚拟机为foo方法创建一个新的栈桢,foo方法执行完毕后栈桢的空间被释放
下面划重点,堆内存和栈内存的主要区别:
- 堆内存是所有线程共享的内存空间,而栈内存是线程私有的内存空间
- 对象的内存空间分配总是发生在堆区,栈内存中则包含了对象的引用地址
- 堆内存满了的时候抛出java.lang.OutOfMemoryError: Java Heap Space,而栈内存满了的时候抛出java.lang.StackOverFlowError
- 栈内存相比堆内存小到微不足道.
参考:
https://www.journaldev.com/4098/java-heap-space-vs-stack-memory