我无法理解垃圾收集中的一些事情。
首先,数据如何分配空间?即在堆栈或堆上(据我所知,所有静态或全局变量都在堆栈上分配空间,局部变量在堆上分配空间)。
其次,GC运行堆栈或堆上的数据?即像Mark / Sweep这样的GC算法会将堆栈上的数据称为root权限吗?然后通过检查堆上的哪些变量引用根集来映射堆上的所有可到达变量。
如果程序没有全局变量怎么办?那么算法如何工作呢?
此致 darkie
答案 0 :(得分:11)
这可能有助于澄清您所询问的平台GC - JVM,CLR,Lisp等。那说:
首先退后一步,通常在堆栈上分配某些局部变量。然而,细节可能因语言而异。以C#为例,只有本地Value Types和方法参数存储在堆栈中。因此,在C#中,foo
将在堆栈上分配:
public function bar() {
int foo = 2;
...
}
或者,动态分配的变量使用堆中的内存。这应该是直观有意义的,否则每次调用new
时堆栈都必须动态增长。此外,这意味着这些变量只能用作分配它们的本地函数中的局部变量,这当然不是真的,因为我们可以拥有(例如)类成员变量。因此,从C#中获取另一个示例,在以下情况下,result
在堆上分配:
public class MyInt
{
public int MyValue;
}
...
MyInt result = new MyInt();
result.MyValue = foo + 40;
...
现在考虑到这一背景,堆上的内存被垃圾收集。堆栈上的内存不需要GC,因为当前函数返回时将回收内存。在较高级别,GC算法通过跟踪在堆上动态分配的所有对象来工作。一旦通过new
分配,该对象将由GC跟踪,并在不再在范围内时收集,并且不再有对它的引用。
答案 1 :(得分:2)
答案 2 :(得分:2)
首先,数据如何分配空间? 即在堆栈或堆上(根据我的 知识,所有静态或全球性的 变量在堆栈上分配空间 和局部变量分配空间 在堆上)。
不,堆栈变量是方法调用和局部变量。调用方法时会创建堆栈帧,并在返回时弹出。
Java和C#中的内存通过调用“new”来分配在堆上。
其次,GC运行堆栈上的数据或 堆?即GC算法 标记/扫描将参考数据 堆栈如root设置吧?然后映射 堆上的所有可到达变量 检查堆上的哪些变量引用 到根集。
在堆上使用GC。
标记和扫描不会被视为最先进的GC算法。 Java和.NET GC现在都使用分代模型。
如果某个程序没有 全局变量?怎么样 算法工作呢?
“全局变量”在Java和C#等语言中的含义是什么?
对象图的根是任意的。我承认我不知道它是如何被选中的。
答案 3 :(得分:1)
阅读this article。这是一个关于单处理器垃圾收集技术的非常好的调查。它将为您提供有关GC的基本理解和术语。然后,跟进Jones和Lins的书“垃圾收集:自动动态内存管理的算法”。与我上面提到的调查文章相反,这本书在网上是免费提供的;你必须买它;但这是值得的。
答案 4 :(得分:1)
Richard and Carl在他们的.NET Rocks中对Windows内存模型进行了非常精彩的演示,包括.NET模型和GC!档案
答案 5 :(得分:0)
您可能会发现Garbage Collection on the Memory Management Reference的简短摘要很有用。
最终,垃圾收集必须从处理器的寄存器开始,因为处理器无法访问的任何对象都可以被回收。根据语言和运行时系统,静态假设线程的堆栈和寄存器也可以访问,以及“全局变量”是有意义的。
Stacks可能会让你获得局部变量。因此,在简单的GC中,您首先要扫描线程上下文,它们的堆栈和全局变量。但在每种情况下都不是这样。有些语言不使用堆栈或具有全局变量。更重要的是,GC可以使用barrier,这样他们就不必每次都查看每个堆栈或全局。一些专门的硬件,例如Symbolics Lisp Machine在寄存器上有障碍!