写作的意义在于分享,在于遇见。
昨天发文后,我收到了一条评论,问我不知道什么是堆内存和栈内存。 因此,才有了今天这篇文章。
数据结构里的栈和堆
如果学过数据结构这门课,一定对“栈”和“堆”这两个词不陌生。
栈 表示一种先进后出(LIFO,last in first out,后进先出)的数据结构。类比生活中,就像是训练有素的服务员堆脏盘子,理应按照从下面开始堆上去的反方向,也就是从上往下开始洗盘子。这里的堆盘子和洗盘子,就是数据的存和取。
堆 在数据结构里,是一种特殊的树结构:一般有最大堆和最小堆。如下图。最小堆根结点都不大于左右孩子。最大堆的根结点都不小于左右孩子。
除了表示一种数据结构,还可以表示内存分配的通用空间。而堆内存,则指的就是后者的含义。
Java 为什么会有两种内存分配方式呢?
栈来存数据时,你只能取出你最后加进去的。这种方式对局部变量来说就刚刚好。因为他们会随着函数的调用,就来了,函数结束,就要消失。栈让追踪变得很简单,因为最后保存的一定是最先被释放的。
但是栈并不适合一些随意的数据,这些数据的 生命周期 并不遵循单独的函数那样。这时, 堆内存 就可以允许你任意去添加或删除这些数据。
所以栈在内存中占的空间,比 Java 堆空间少太多了。因为方法一结束,在这个方法里创建的所有变量都会被永久清除掉。
Java 中的栈内存用于静态内存分配和线程的执行。如果栈内存满了,会抛出异常:java.lang.StackOverFlowError 。而且是线程安全的,因为线程之间是被隔离开来的。
Java 中的堆内存为 Java 对象 和 JRE 类 动态分配内存。如果堆内存满了,抛出的异常是: java.lang.OutOfMemoryError。
栈内存和堆内存的不同主要体现在以下几点:
- 程序应用上:栈内存是在执行栈帧的时候,被方法所使用,堆内存是被整个应用在所有运行时间使用。
- 存储的东西:栈内存只存主要变量和堆中创建的对象的引用,堆内存存所有被创建的对象。
- 使用顺序:栈内存就是用 LIFO 的顺序管理的,堆内存则是通过复杂的内存管理技术来存取的(之前文章提过的年轻代、年老代和永久代)。
- 效率上:栈内存要比堆内存快。
- 分配和回收:方法被调用的时候,栈内存就被开辟了,方法返回时,就被回收;
当新对象被创建的时候,堆内存被开辟,如果没有任何引用了,就会被垃圾回收器回收掉。
参考链接: