方法调用期间创建的本地Java对象的生命周期

方法调用期间创建的本地Java对象的生命周期,java,garbage-collection,Java,Garbage Collection,在方法调用中,如果我在调用期间创建对象。这些东西什么时候被垃圾收集 它们被放置在堆上,然后与堆上的其他对象一起被垃圾收集。还是因为不需要它们而提前收集它们。该方法的执行已完成。在方法范围内创建的对象在方法关闭时有资格进行垃圾收集,除非该引用作为返回值传回。在这种情况下,调用方可能会也可能不会挂起该引用,并阻止它被gc'd 由于垃圾回收器根据自己的指示灯在自己的线程上运行,因此您不一定知道何时清理对象,也不一定知道分配到其他位置的对象是否也符合条件。这并不是那么容易-最终每个对象都是通过某种方法创

在方法调用中,如果我在调用期间创建对象。这些东西什么时候被垃圾收集


它们被放置在堆上,然后与堆上的其他对象一起被垃圾收集。还是因为不需要它们而提前收集它们。该方法的执行已完成。

在方法范围内创建的对象在方法关闭时有资格进行垃圾收集,除非该引用作为返回值传回。在这种情况下,调用方可能会也可能不会挂起该引用,并阻止它被gc'd


由于垃圾回收器根据自己的指示灯在自己的线程上运行,因此您不一定知道何时清理对象,也不一定知道分配到其他位置的对象是否也符合条件。

这并不是那么容易-最终每个对象都是通过某种方法创建的

VM/编译器需要进行转义路径分析,以检测此对象的引用是否可以以某种方式转义-想象一下调用newObject.toString()。您和我都知道(希望)这不会造成任何伤害,并且对象仍然没有被引用,因为它不会将自身链接到全局变量。但虚拟机没有

虽然现代虚拟机将进行此类分析,并处理垃圾收集中特殊的真实短期对象,但从“高级”的角度来看,它们只是对象。其他一切都是复杂的低级优化


不管怎么说,正如duffymo所说,这些对象何时被释放是不确定的。

方法的执行已经结束,而现在对象超出了范围这一事实是不相关的。
垃圾收集是运行时系统的一种隐式操作,与代码并行运行在单独的线程中,实现特定的垃圾收集算法。
垃圾收集线程在不可预测的时间运行,但通常情况下,根据java文档,每秒钟左右运行一次,当内存几乎用完时,评估哪些对象符合垃圾收集的条件,即没有来自根指针(例如静态变量)的引用。
因此,根指针可访问的每个对象都会被标记,然后递归地标记这些对象引用的对象等。
这可能意味着扫描整个进程空间。完成后,上一次扫描中未“标记”的所有对象都将进入空闲列表(GC)。
正如你所见,这是一项繁重的行动

该方法的执行已经完成 完成

因此,您不在您调用的方法的范围内,因为它已完成,这一事实与此无关。这并不意味着运行时知道对象已经完成(因为GC是并行运行的)。
它不像C++那样,在方法的末尾,程序员会调用对象上的删除,因为它不需要。在Java中,在方法末尾不会自动调用“delete”。
GC线程最终会意识到,不再有对该方法和CG在堆上分配的对象的引用。
如果需要,您可以通过以下方式随时调用GC:

System.gc();
但是GC迟早会运行。
需要注意的一点是,只要有根指针对方法的引用,它就不能是GC的引用。

因此,如果在方法中通过
new
在堆上创建一个对象,并将引用存储在静态容器中或将其返回给调用方,对象比方法更有效。

@duffymo:这不取决于函数返回后新创建的对象的引用是否存在吗?例如,一个存储在调用方作用域中的集合中的对象。@user-在这种情况下,对象的作用域已更改,并且可能不受GC的影响。“在方法作用域中创建的对象…”对我来说,这意味着它不是由用户传入的。有一点您是对的:如果在作用域中创建的对象作为返回值传回,那么调用方可能会保留引用并阻止它被gc调用。我将修改我的答案。对象可以通过许多其他方式逃逸,不仅仅是作为返回值。每次调用对象上的方法或将其用作方法参数时,都不能再简单地确定对象生命周期。我的意思是,系统不能简单地区分对象m1(){object a=new Thing();return null;}和对象m2(){object a=new Thing();a.toString());return null;},其中在“toString”中,新对象被分配给一个静态变量。“b.anotherCall(a)”也同样适用。。。还是我们在谈论不同的事情?自从Smalltalk时代以来,垃圾收集已经有了很大的改进。商业级虚拟机不再像这样了。google可以提供很多关于实际算法的信息。System.gc()或多或少是对VM的一个建议,即现在触发gc是个好主意。您不能依赖这一点得到确认,而且(即使VM同意),在收集gc()垃圾之后,您也可以依赖这一点。这总是异步的。@mtraut:我也倾向于这样做。但是javadocs似乎不这么说:
当控件从方法调用(System.gc)返回时,Java虚拟机已经尽了最大努力从所有丢弃的对象中回收空间
我的注释中的句子应该是“(即使虚拟机同意)你不能依赖……”. 正如你所说的,这是它最大的努力。这意味着这取决于VM——谁知道得最清楚。要对你的第一句话挑三拣四:对象没有超出范围——引用它的变量已经超出范围。这或多或少是这个地区所有混乱的根源。