下面的代码是否会在类“死”之前收集垃圾?

时间:2010-04-04 03:03:41

标签: c# java .net garbage-collection

假设我们在一个类中有以下代码:

//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是否也以同样的方式工作!

由于

4 个答案:

答案 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可能不会执行此垃圾收集,并且可以按任何顺序执行此操作。