在Java中,堆内存是由垃圾回收器进行垃圾回收的。
那么栈内存也被垃圾回收吗?
栈内存是如何被回收的?
在Java中,堆内存是由垃圾回收器进行垃圾回收的。
那么栈内存也被垃圾回收吗?
栈内存是如何被回收的?
栈内存包含方法参数和局部变量(确切地说:对象的引用和原始类型的变量本身)。当你离开方法时,它们将被自动删除。如果这些变量是对象的引用,则对象本身位于堆上,并由垃圾回收器处理。
因此,栈不会像堆一样进行垃圾回收,但栈本身是一种自动内存管理方式(早于垃圾回收)。
Thomas Pornin提供了更详细的答案,欲了解更多细节请参考。
在Java中,堆栈不会进行垃圾回收。
为方法调用分配的堆栈将在方法返回时释放。由于这只是一个非常简单的LIFO结构,因此不需要进行垃圾回收。
堆栈和垃圾回收交互的一个地方是,堆栈上的引用是GC根(这意味着它们是从中决定可达性的根引用)。
堆栈可能会被垃圾回收。然而,在大多数JVM实现中,它被处理为一个“堆栈”,这意味着它不允许进行垃圾回收。
我们所说的堆栈是方法激活上下文的积累:对于每个调用的方法,这是包含方法参数、本地变量、指向调用方法上下文的隐藏指针和保存指令指针的概念结构。从Java语言本身无法访问激活上下文。当方法退出(使用return
或由于抛出异常)时,上下文变得无用。当方法A调用方法B时,保证当A重新获得控制权时,B的上下文已经变得无用。这意味着B的上下文寿命是A上下文寿命的子范围。因此,(对于给定线程的)激活上下文可以按照LIFO(“后进先出”)规则分配。简单来说,就是一个堆栈:新的激活上下文被推到上下文堆栈的顶部,并且在顶部的上下文将首先被处理。
call-with-current-continuation
函数),因为这些游戏打破了上述LIFO规则。推到堆栈上
),并且随着程序运行,会自动从顶部删除(从堆栈中弹出
)。它不会被垃圾回收 - 也没有必要,因为一旦数据从堆栈中弹出,该内存就会自动回收。当我说回收时,我并不是指它被解除分配 - 只是堆栈内存中下一个数据将存储的位置会减少,因为数据被弹出。Java 中的所有对象都分配在堆上。(至少根据规范,如果它们透明地表现为在堆上分配,则实际实现可能将它们分配在堆栈上。)
确切可回收的内容有点微妙。如果一个对象的唯一引用在单个堆栈帧中,并且可以证明该引用不会再次使用,则可以回收该对象。如果对象仅用于读取字段,则该字段读取可能会被优化向前,并且对象的回收可能比您预期的要早。
除非您正在使用 finalizers(或者可能是 Reference
s),否则通常不需要担心这个问题。在这种情况下,您应该小心使用锁/易失性来强制执行 happens-before
关系。
当线程停止时,通常整个堆栈将被释放。
在编程中,当你在方法中使用内部变量或进行方法调用时,数据会像从堆栈中推入和弹出一样处理,你不需要过多关注这个过程。
堆栈上的所有内容都被垃圾回收器视为全局根。因此,可以肯定地说堆栈是“垃圾回收”的。