Java 中的堆内存是垃圾回收的。

堆栈垃圾也被收集了吗?

栈内存是如何回收的?

没有正确的解决方案

其他提示

堆栈上的内存包含方法参数和局部变量(确切地说:对象和变量本身用于原始类型的引用)。如果您离开该方法,那将自动删除。如果变量是引用(对象),则对象本身在堆上,并由垃圾收集器处理。

因此,堆栈不是像堆一样收集的垃圾,但是堆栈是自动内存管理的一种形式(早于垃圾收集)。

一个 更详细的答案由Thomas Pornin给出, ,看看更多细节。

该堆栈不是在Java收集的垃圾。

当方法返回时,分配给给定方法调用的堆栈将被释放。由于这是一个非常简单的LIFO结构,因此无需收集垃圾。

堆栈和垃圾收集相互作用的一个地方是堆栈上的参考是GC根(这意味着它们是决定可及性的根参考)。

堆栈 可以 收集垃圾。但是,在大多数JVM实现中,它被称为“堆栈”,从定义上讲,它排除了垃圾收集。

我们称之为堆栈的是积累 方法激活上下文: :对于每个调用方法,这是包含方法参数,局部变量,通往调用方法上下文的隐藏指针的概念结构,以及一个保存指令指针的插槽。从Java语言本身无法访问激活上下文。当方法退出时,上下文将无用(使用 return 或由于抛出的例外)。碰巧的是,当一种方法A调用A方法B时,可以保证当A恢复控制时,B的上下文就变得毫无用处。这意味着B上下文的寿命是A上下文的子范围。因此,可以用LIFO(“最后,首先”)纪律来分配激活上下文(对于给定线程)。用更简单的话来说,堆栈:新的激活上下文被推在上下文的顶部,顶部的上下文将是第一个被处置的上下文。

实际上,激活环境(也称为 堆栈框架)在专用区域中以堆栈顺序串联。该区域是从操作系统启动时从操作系统中获得的,并且在线程终止时,操作系统将其恢复。堆栈的顶部由特定指针指定,通常包含在CPU寄存器中(这取决于JVM是解释还是编译代码)。 “指向呼叫者上下文的指针”是虚拟的;呼叫者的上下文必然位于堆栈顺序下方。 GC不干预:堆栈的区域是从线程活动本身同步创建和回收的。这也是它在许多语言中运作的方式 C, ,根本没有GC。

现在,没有什么可以阻止JVM实现进行否则,例如,在堆中分配激活环境并将其收集到GC中。由于堆栈分配更快,因此通常在Java Virtual Machines中不执行此操作。但是其他一些语言需要做这些事情,最值得注意的是那些玩耍的语言 连续 同时仍在使用GC(例如 方案 及其 call-with-current-continuation 功能),因为这样的游戏打破了上面解释的LIFO规则。

内存的堆栈部分就像“堆栈”一样工作。我知道这听起来很不好,但这正是它的工作方式。数据被添加到顶部,彼此之间pushed onto the stack)并自动从顶部删除(popped off the stack)随着您的程序运行。它不是收集的垃圾 - 不需要是,因为一旦数据从堆栈中弹出后,该内存就会自动回收。而且,当我说回收时,我并不是说它被取消分配 - 只是堆栈内存中的位置将降低下一个数据的存储,因为数据弹出。

当然,这并不是说您根本不必担心堆栈。如果您多次运行递归功能,它将最终消耗所有堆栈空间。如果您调用许多函数,尤其是当它们具有许多参数和/或本地变量时,情况也是如此。

但最重要的是,随着功能输入和离开范围,使用并回收了堆栈的内存。因此,在程序执行结束时,所有堆栈内存都是免费的,然后将其释放回操作系统。

如果引用堆栈上使用的内存,则不会对其进行垃圾回收。
java虚拟机使用显式字节码指令来保留和释放堆栈上的内存,这些指令由编译器生成并管理堆栈上的int、boolean、double和对象引用等原语的生命周期。
已经计划实现所谓的尾部调用优化,一旦知道它们不再使用,就会从堆栈中删除一些条目,但我不知道有任何 jvm 已经支持这一点。
因此,堆栈本身没有垃圾收集,只有编译器生成入栈和出栈指令来管理内存使用。

堆栈本身是线程的一部分。堆栈在线程对象创建时分配,并在线程终止且线程对象不再被引用后进行垃圾回收。

Java中的所有对象均分配在堆上。 (至少就规格而言,如果实际实施方式可以在堆栈上分配它们,如果它们透明地表现得像它们在堆上一样。)

恰好是收藏品有点微妙。如果对对象的唯一引用是在单个堆栈框架中,并且可以证明不会再次使用引用,则可以收集对象。如果该对象仅用于读取字段,则该字段读取可能是向前优化的,并且对对象的收集到您可能预期的。

除非您使用最终确定器(或者大概是 ReferenceS)。在这种情况下,您应该小心并使用锁/波动来强制执行 happens-before 关系。

当线程停止时,通常会处理整个堆栈。

堆栈上的所有内容都被垃圾收集器视为全球根。所以,是的,您绝对可以说堆栈是“收集垃圾”。

没有人,当您在方法,方法调用等过程中具有内部变量时,将数据推开并从堆栈中弹出。您不需要关心这一点。

否。堆栈不是在Java收集的垃圾。每个线程都有自己的堆栈,并包含:

  1. 方法特定的值(短寿命)和
  2. 对对象的引用,在堆上创建,并由该方法引用

对于每个方法调用,将这些值作为堆栈帧推到堆栈中。由于堆栈遵循“最后一列”顺序,因此在每个方法调用的末尾,每个堆栈帧包含所有特定方法的数据以及对对象(如果有)的引用(如果有的话)。

因此,一旦方法/程序超出范围,堆栈中的数据就会自动清洁。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top