Java是否收集了堆栈垃圾?

2021/01/17 08:51 · java ·  · 0评论

堆内存是用Java收集的垃圾。

是否也收集堆栈垃圾?

如何回收堆栈内存?

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

因此,堆栈不是以与堆相同的方式进行垃圾回收,而是堆栈本身就是一种自动内存管理的形式(它早于垃圾回收)。

一个更详细的解答是由托马斯Pornin给出的,考虑这样做的更多细节。

堆栈不是用Java垃圾回收的。

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

堆栈和垃圾回收交互的一个地方是,堆栈上的引用是GC根(这意味着它们是确定可达性的根引用)。

堆栈可能会被垃圾收集。但是,在大多数JVM实现中,它都是作为“堆栈”来处理的,根据定义,该堆栈会排除垃圾回收。

我们所谓的堆栈是方法激活上下文的累积:对于每个调用的方法,这是概念性结构,其中包含方法参数,局部变量,指向调用方法上下文的隐藏指针以及用于保存指令的插槽指针。无法从Java语言本身访问激活上下文。方法退出时,上下文变得无用(带有return或由于抛出异常而导致)。碰巧的是,当方法A调用方法B时,可以确保当A重新获得控制权时,B的上下文将变得无用。这意味着B上下文的生存期是A上下文的生存期的子范围。因此,可以使用LIFO(“后进先出”)规则来分配(对于给定线程)激活上下文。用简单的话来说就是一个堆栈:将新的激活上下文推到上下文堆栈的顶部,并且最上面的上下文将是第一个被丢弃的上下文。

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

现在,没有什么可以阻止JVM实现的其他操作,例如,在堆中分配激活上下文并由GC收集它们。由于堆栈分配更快,因此在Java虚拟机中通常不这样做。但是某些其他语言需要执行此类操作,尤其是那些仍在使用GC的情况下连续播放的语言(例如Scheme及其call-with-current-continuation功能),因为此类游戏违反了上面解释的LIFO规则。

存储器的堆栈部分就像“堆栈”一样工作。我知道这听起来很糟糕,但这就是它的工作原理。数据被添加到顶部,彼此之间(pushed onto the stack),并popped off the stack在程序运行时自动从顶部(删除它不是垃圾收集的-不必这样,因为一旦从堆栈中弹出数据,该内存就会自动回收。而且,当我说回收时,我并不是说它会被取消分配-只是因为弹出数据,减少了堆栈存储器中将存储下一个数据的位置。

当然,这并不是说您完全不必担心堆栈。如果您多次运行递归函数,它将最终耗尽所有堆栈空间。如果调用许多函数,尤其是在它们具有许多参数和/或局部变量的情况下,则相同。

但最重要的是,随着函数自动进入和离开范围,堆栈的内存将被使用和回收。因此,在程序执行结束时,所有堆栈内存都将释放,然后释放回操作系统。

如果您引用堆栈上使用的内存,则不会进行垃圾回收。

Java虚拟机使用显式字节码指令在堆栈上保留和释放内存,这些指令由编译器生成,并管理堆栈中诸如int,boolean,double和object-references之类的原语的生存期。


已经有计划实现所谓的尾部调用优化,一旦知道不再使用它们,它们就会从堆栈中删除一些条目,但是我不知道任何已经支持此功能的jvm。


因此,堆栈本身没有垃圾回收,只有编译器生成推入和弹出指令来管理内存使用。

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

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

确实,可收藏的东西有些微妙。如果唯一引用对象是在单个堆栈框架中,并且可以证明该引用将不再使用,则可以收集该对象。如果对象仅用于读取字段,则可能会向前读取该字段进行优化,并且对象可能比您预期的要早收集。

除非您使用终结器(或可能是References),否则通常这并不重要在这种情况下,您应该小心并使用lock / volatile来强制建立happens-before关系。

当线程停止时,通常整个堆栈将被释放。

垃圾收集器将位于堆栈上的所有内容都视为全局根。因此,是的,您可以肯定地说堆栈是“垃圾收集”。

没有人,因为您在方法中,方法调用期间等中具有内部变量,所以将数据从堆栈中压入和弹出。您无需担心这一点。

不。堆栈不是用Java进行垃圾回收的。每个线程都有自己的堆栈,并包含:

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

对于每个方法调用,这些值将作为堆栈帧推送到堆栈。由于堆栈遵循“后进先出”的顺序,因此在每次方法调用结束时,都会弹出包含所有方法特定数据和对象引用(如果有)的每个堆栈帧。

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

本文地址:http://java.askforanswer.com/javashifoushoujileduizhanlaji.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!