5

我刚开始使用 C# 作为我的语言的 .NET Framework。我有点理解 Java 中 GC 的概念,并且今天在 .NET 中重新审视了相同的概念。

在 C# 中,值类型被放入堆栈(与 Java 的情况相同,局部变量被放入堆栈)。但在 C# 中,甚至struct包含在值类型中。因此,偶数structs 被放入堆栈。在最坏的情况下,有许多方法调用,堆栈中大量填充了许多方法,每个方法都有许多本地值类型,并且许多struct本身具有许多本地值类型的 s,垃圾收集器是否会影响堆?根据我的研究(以及我所学到的部分内容),我知道它不会这样做。主要是因为操作堆栈内容会涉及大量开销,此外,GC 仅咨询堆栈以查找引用 - 仅此而已。

只是添加与同一主题相关的另一个问题:强制调用 GC(如System.gc()在 Java 中,不确定 C# 等效项),并不能确保当时和那里调用 GC 例程。那么我应该在哪里进行这样的调用 - 我希望我需要 GC 运行的地方,或者任何随机的地方,因为不能保证我的调用会立即触发 GC?或者我应该把这些东西留给运行时环境而不去管它吗?

注意:我添加了 Java 标记,因为我试图从那里链接概念。我知道 GC 在两个单独的运行时环境中的内部功能肯定会有所不同,但我想基本概念是相同的。

4

5 回答 5

2

没有垃圾收集不会影响 java 堆栈上的对象。

GC 只影响 jvm 堆中的对象。java GC 过程是多层的,可能非常复杂,值得一读。查看类似的网站:http: //javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html以很好地掌握它的运作方式。

至于强制系统的 GC那是个坏主意。当需要运行 GC 时,jvm 会更好地了解您。如果您尝试分配一个大对象,jvm 将确保空间适合您,而无需告诉它运行 GC。

编辑 我的错,你更关心 C# 而不是 java。内存管理的相同原则适用,堆栈不受影响,不显式运行 GC 等。C# 旨在以与 java 类似的方式运行。 http://msdn.microsoft.com/en-us/library/ms973837.aspx

于 2012-07-26T14:34:51.183 回答
2

堆栈不需要垃圾收集器的帮助;因为,当您移出堆栈帧(堆栈中当前执行的范围)时,整个帧(包括内容)在您创建新堆栈帧时被释放(并覆盖)。

function foo(int a, int b) {
  int i;
  doStuff();
}

创建一个堆栈帧(粗略的可视化)

---- Frame Start ----
(value for parameter a)
(value for parameter b)
(other items needed for tracking execution)
(extra stack frame space
  (value for stack allocated i)
)
---- End of Frame ----

进入函数时,堆栈分配的变量在分配帧时分配,退出帧时,整个帧被丢弃,为帧分配的变量释放内存。

请记住,Java 通常在堆栈上分配对象引用和堆栈本地原语,而不是整个对象。只有少数最近的优化允许在框架外无法访问的对象的堆栈内分配;它有这样的条件,它不被认为是你可以指望的东西。

也就是说,堆栈帧中的引用通常指向堆,通常是垃圾收集。

于 2012-07-26T14:32:48.820 回答
1

.NET 垃圾收集在 MSDN 上的垃圾收集中进行了深入解释。垃圾收集器仅在托管堆中跟踪内存。

于 2012-07-26T14:35:41.083 回答
1

不。AFAIK GC 不会影响堆栈。它只影响 HEAP 内存。堆栈框架将在方法调用时创建,并在方法退出时删除。

编辑

这篇MSDN 文章解释了 GC 在 .NET 框架中的工作原理。

于 2012-07-26T14:31:30.240 回答
1

如果您为 .NET 阅读此内容,则它仅适用于托管堆:

http://msdn.microsoft.com/en-us/library/ee787088.aspx

MSDN好像是个资料宝库,这里是CLR中关于GC的父主题:

http://msdn.microsoft.com/en-us/library/0xy59wtx

于 2012-07-26T14:32:28.500 回答