垃圾收集是否会影响堆栈?

时间:2012-07-26 14:29:56

标签: c# java .net

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

在C#中,值类型被放入堆栈(与Java的情况相同,其中局部变量被放入堆栈中)。但在C#中,偶数struct也包含在值类型中。因此,即使struct被放置在堆栈上也是如此。在最糟糕的情况下,有许多方法调用,并且堆栈使用许多方法进行大量填充,并且每个方法都有许多本地值类型,并且许多struct本身具有许多本地值类型,垃圾收集器会影响堆栈吗?从我研究的内容(以及我所教的内容),我明白它不会这样做。主要是因为操纵堆栈内容将涉及大量开销,此外,GC只会查询堆栈以查找引用 - 仅此而已。

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

注意:我添加了Java标记,因为我试图从那里链接概念。我理解GC在两个独立的运行时环境中的内部功能肯定会有所不同,但我想底层的概念是一样的。

5 个答案:

答案 0 :(得分: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通常会在堆栈上分配对象引用和堆栈本地原语,而不是整个对象。只有少数最近的优化允许在帧外无法访问的对象的堆栈内分配;它有这样的条件,它不被认为是你可以指望的东西。

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

答案 1 :(得分:2)

垃圾收集不会影响Java堆栈上的对象。

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

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

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

答案 2 :(得分:1)

没有。 AFAIK GC不会影响堆栈。它只影响HEAP记忆。堆栈帧将在方法调用时创建,并将在方法退出时删除。

修改

这个MSDN article解释了GC在.NET框架中的工作原理。

答案 3 :(得分:1)

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

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

MSDN似乎是一个信息宝库,这里是CLR中GC的主题:

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

答案 4 :(得分:1)

.NET垃圾收集在MSDN上的Garbage Collection中有详细解释。垃圾收集器仅在托管堆中跟踪内存。