假设我们在一个类中有以下代码:
//class code
TextBox t = new TextBox();
ListBox l = new ListBox();
我们有两种可能的情况:
首先,我们将qem1
声明为类变量(或属性,因为它们在Java World中称为它):
//class variable
QuickEntryMediator qem1 = new QuickEntryMediator(t,l);
在第二个中,我们在一个方法中声明它:
//method variable
QuickEntryMediator qem2 = new QuickEntryMediator(t,l);
所以,我会说在课程超出范围之前,qem1永远不会被收集垃圾,而在qem2中,可能是垃圾收集后的任何时候收集的垃圾。这是真的吗?
我正在寻找C#(。net)和Java的答案,因为我不确定GC是否也以同样的方式工作!
由于
答案 0 :(得分:1)
C#和Java都会这样做。 GC将检查定义为任何静态变量(类变量)的根或直接或间接从线程堆栈引用的任何变量。
当方法(或块)结束时,方法中实例化的对象将超出范围,除非它在类或对象变量中返回或保存在该范围之外。
顺便说一下,一个类在进程持续时间内永远不会超出范围,除非在Java中收集ClassLoader并且在C#中卸载程序集。如果你在谈论一个对象变量(非static
),那么当对象本身的时候,该对象的所有引用都会“超出范围”。
此外,这完全取决于GC,因此可能无法立即收集对象。
答案 1 :(得分:1)
我是Java和C#,在变量的最后一次引用超出范围之后,与变量关联的数据被垃圾收集 一段时间 。变量符合GC条件后,有效垃圾回收的具体时刻通常不在语言规范中定义。
很难回答你的问题,因为不确定最初分配QuickEntryMediator对象的qem1和qem2变量是局部变量还是实例变量(甚至是全局静态变量);片段节目没有显示出来。
此外,l和t变量本身与何时/如果将删除QuickEntryMediator对象无关,它们只会使图片复杂化。然而,您显示这些内容的意图可能是尝试从QuickEntryMediator对象生命周期中推断TextBox / ListBox本身的生命周期,以防QuickEntryMediator引用它们。
答案 2 :(得分:1)
请注意,在C#中(我也相信Java),对象有资格进行收集,不再强烈引用(直接或间接),这可能在引用变量超出范围之前发生,只要不再使用该引用。只要运行时可以确定不再需要它们(即,程序完成对对象的任何引用),就可以在仍在范围内时收集对象。
所以qem2
在'die'*中定义的方法之前很久才有资格收集,我认为你的意思是返回),但这完全取决于qem2
的使用方式。
使用以下简单的C#代码,在Main()
开头创建的互斥锁可能在创建后的任何时刻被垃圾收集 - 它可能不会生效到Main()
范围的末尾,因为什么都没有引用它创建后。
static void Main(string[] args)
{
bool createdMutex;
System.Threading.Mutex mutex = new
System.Threading.Mutex(true,"myAppMutex",out createdMutex);
if (!createdMutex)
{
MessageBox.Show( "an instance of myApp is already running", "myApp running...");
return;
}
Application.Run();
}
有关详细信息,请参阅以下内容。
请注意,至少在.NET中,在调试器下运行会使对象保持活动状态直到作用域结束,因此如果您要测试它,请确保在调试情况之外执行此操作。
答案 3 :(得分:0)
我们必须区分Java规范和Oracle流行的HotSpot实现。 Java标准不保证垃圾收集的时间。在程序关闭之前,JVM可能不会执行此垃圾收集,并且可以按任何顺序执行此操作。