【问题标题】:Will the Type Object be garbage collected?类型对象会被垃圾收集吗?
【发布时间】:2019-08-23 02:14:25
【问题描述】:

例如,我有一个 A 类和一个方法 f。

Class B
{
    void aMethod(){}    
}

void f()
{
    var a= new B();
    a.aMethod();
}

当执行一个方法时,CLR 将首先在堆上启动基本类型对象。因此,在 f 执行的第一条语句之前,将在堆上分配并初始化对象 B Type Object

那么在 f 被执行之后,B Type Object 会被垃圾回收吗?(除了B 实例之外,B Type Object 是否还有一些特殊的root?)

为了澄清,B Type Object 指的是代表B 类型的System.Type 对象

我正在阅读本书CLR via C# 的第 4 章。

【问题讨论】:

  • “类型对象”是什么意思?你说的是B 存储在a 中的实例,还是说代表B 类型的System.Type 对象?
  • “那么在执行 f 之后,B 类对象会被垃圾回收吗?” - 简短回答 不会立即何时取决于 CLR 并且是一个复杂的主题
  • @AlexWei 我不知道确切的答案,但我怀疑System.Type 对象永远不会被垃圾收集。无论如何,它们都很轻巧。
  • Related question(如果我理解你的意思,那就是)。
  • 要记住的是,CLR 不必遵循与您相同的规则。元数据的处理方式与常规对象实例不同。

标签: c# garbage-collection clr


【解决方案1】:

f() 方法完成后,在该方法中创建的B 对象的实例变为有资格进行收集。这并不一定意味着它会立即被收集。每当 GC 碰巧下一次运行时,它就会被收集,这可能是方法完成时,也可能不是。

但听起来您可能正在谈论元数据,这是另一种用于描述对象类型的对象实例,例如 Type 类型。

所以我们需要讨论两件事:Type 实例和元数据。没有Type 实例只是因为您调用了f() 方法并第一次使用了B 对象。每种类型都有 元数据,但它本身通常并不存在于堆中,当然也不会因为您第一次调用f() 而被分配。相反,特定程序集的所有元数据都存在于程序集目标代码中的表中。整个表都装有程序集。您可以在此处阅读更多信息:

https://en.wikipedia.org/wiki/Metadata_(CLI)

这很令人困惑,因为还有一个 Object 类型,这在 .Net 中意味着完全不同的东西,并且在问题中使用 Object 这个词会使事情变得混乱而不是帮助。但是.Net 中的Object 类型不会以任何特殊方式自动植根。当实例不再可访问时,它们就像其他任何东西一样有资格被收集。

【讨论】:

  • 泛型类型可以在运行时创建;我不认为它们有资格被收集,但大多数程序都没有创建足够多的它们,这会成为一个问题。
  • 是的,并且可以在运行时加载程序集,向表中添加更多元数据。但问题中的示例代码都不是问题的一部分,我怀疑只会进一步混淆 OP。
  • 你提到的Object类型是指包含Type object ptrSync block index的类型吗? Object 类型是 Type 类型的一个实例,它在元数据中并且始终存在。我理解你的意思吗?
  • After the f() method finishes, the instance of the B object created in the method becomes eligible for collection. 从技术上讲,它甚至可以在此之前符合条件。 devblogs.microsoft.com/cbrumme/…
猜你喜欢
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 2019-01-14
相关资源
最近更新 更多