是什么破坏了java中的局部变量?

St.*_*rio 5 java garbage-collection

我怀疑方法局部变量仅在方法执行时才存在.此外,GC EdenLong-generation块溢出时触发(轻微/主要GC)等......所以,如果在方法体的末尾Eden没有溢出,那么就不需要触发GC.尽管没有触发主要/次要GC,我们将销毁所有局部变量.怎么做?

Ste*_*n C 9

方法局部变量(或通常称为"局部变量")在每个线程的堆栈上分配.变量本身不受垃圾回收的影响.当方法调用终止(正常或异常)时,它们会自动回收.

物体是另一回事.对象(包括数组)通常在堆上分配1,并且它们受垃圾回收的影响.


那么由方法分配并分配给局部变量的对象(或数组)呢?

首先,局部变量保存对象的引用.该对象存储在堆中(参见上文).

当垃圾收集器运行时(你通常不知道什么时候会这样!)它将检查任何现有的局部变量以查找仍在进行中的方法调用.变量包含对象的引用,这些对象被添加到要保留的对象列表中......并检查它们对其他对象的引用,等等.


因此,总之,当方法调用结束时,局部变量会自动销毁,但这些变量引用的对象将继续存在,直到GC(最终)发现它们无法访问.


1 - 最近的Hotspot JIT编译器有一个称为"转义分析"的可选优化,用于查找由方法调用创建的对象可以在线程堆栈上分配的情况.默认情况下不启用此功能.如果在堆栈上分配了一个对象,那么当方法调用结束时它将被回收.GC不涉及.

2 - 您说:"当Eden或长代数据块溢出(次要/主要GC)等时触发GC ......".这不一定是这样.在各个空间填满之前触发一些低暂停收集器.但是,这不会改变上述任何一种情况.


Jon*_*sky 6

垃圾收集器 - 收割机,有时是已知的 - 按照自己的计划运行,并收集不参考的对象.当然,在方法退出后无法引用局部变量,因为它们超出了范围,因此对于程序来说它们已经死了*,但它们仍然存在于堆上,直到GC运行.

在正常情况下(以及大多数异常情况),您无需告诉收割者何时开展工作.它会在需要时静静地来,带走那些不再需要的东西.这是使用高级语言工作的主要优点之一:可以安全地假设您永远不需要考虑管理死对象的释放等问题.你可以把它们扔到肩膀上,并且知道它们永远不会打扰你.我想有一些高性能,高需求的应用程序需要摆弄GC,但这是一个优化,除非你有相反的确实好的证据,否则应该总是假定为时过早.

*当然,除了返回到调用函数的局部变量,它可能成为该范围内的局部变量,并获得更多的生命租约.一般来说,规则是:如果代码的某些部分仍然关心变量,它将不会被垃圾收集,如果程序的任何部分都不关心它,那么您不需要考虑它.

  • 它在 Java 中从未被称为“收割者”。或者至少,不是来自任何可靠/可信的来源。 (2认同)
  • @StephenC我不认为这太重要了.至少,我理解Jon试图说的话. (2认同)
  • “当然,在方法退出后不能引用局部变量。”如果所讨论的方法返回了局部变量,该怎么办? (2认同)