压缩发生后GC如何更新引用 [英] How does the GC update references after compaction occurs

查看:176
本文介绍了压缩发生后GC如何更新引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.NET垃圾收集器收集对象(回收它们的内存)并执行内存压缩(将内存碎片保持为最小)。



我在想,因为应用程序可能有许多对象的引用,当GC(或CLR)由于GC进行压缩而导致对象的地址发生变化时,GC(或CLR)如何管理对这些对象的引用。



实现有点棘手,原生代码和托管代码之间没有真正的区别,它们都是机器代码。对象引用没有什么特别之处,它只是运行时的一个指针。所需要的是收集器找回这些指针并将它们识别为引用被管理对象的类型的可靠方法。不仅仅是在指向对象在压缩时移动时更新它们,还要识别能够确保对象不会过早收集的实时引用。



这很简单对于存储在GC堆中存储的类对象中的任何对象引用,CLR知道对象的布局以及哪些字段存储指针。存储在堆栈或cpu寄存器中的对象引用并不那么简单。与本地变量和方法参数类似。



执行托管代码的关键属性使其与本地代码截然不同,因为CLR可以可靠地迭代托管代码拥有的堆栈帧。通过限制用于设置堆栈帧的代码的种类来完成。这在本地代码中通常是不可能的,帧指针省略优化选项特别讨厌。

堆栈框架首先可以让它找到存储在堆栈上的对象引用。并让它知道该线程当前正在执行托管代码,以便还应该检查cpu寄存器的引用。从托管代码转换到本地代码需要在收集器识别的堆栈上写入一个特殊的cookie。因此,它知道任何后续的堆栈帧都不应该被检查,因为它们将包含任何不会引用托管对象的随机指针值。



你可以看到这个在调试器中启用非托管代码调试时。查看Call Stack窗口并记下[Native to Managed Transition]和[Managed to Native Transition]注释。这是调试器识别这些cookie。它也很重要,因为它需要知道本地窗口是否可以显示任何有意义的内容。栈走也暴露在框架中,请注意StackTrace和StackFrame类。对于沙盒,它非常重要,代码访问安全性(CAS)执行堆栈散步。


The .NET Garbage Collector collects objects (reclaims their memory) and also performs memory compaction (to keep memory fragmentation to minimum).

I am wondering, since an application may have many references to objects, how does the GC (or the CLR) manage these references to objects, when the object's address changes due to compaction being made by the GC.

解决方案

The concept is simple enough, the garbage collector simply updates any object references and re-points them to the moved object.

Implementation is a bit trickier, there is no real difference between native and managed code, they are both machine code. And there's nothing special about an object reference, it is just a pointer at runtime. What's needed is a reliable way for the collector to find these pointers back and recognize them as the kind that reference a managed object. Not just to update them when the pointed-to object gets moved while compacting, also to recognize live references that ensure that an object does not get collected too soon.

That's simple for any object references that are stored in class objects that are stored on the GC heap, the CLR knows the layout of the object and which fields store a pointer. It is not so simple for object references stored on the stack or in a cpu register. Like local variables and method arguments.

The key property of executing managed code which makes it distinct from native code is that the CLR can reliably iterate the stack frames owned by managed code. Done by restricting the kind of code used to setup a stack frame. This is not typically possible in native code, the "frame pointer omission" optimization option is particularly nasty.

Stack frame walking first of all lets it finds object references stored on the stack. And lets it know that the thread is currently executing managed code so that the cpu registers should be checked for references as well. A transition from managed code to native code involves writing a special "cookie" on the stack that the collector recognizes. So it knows that any subsequent stack frames should not be checked because they'll contain random pointer values that don't ever reference a managed object.

You can see this back in the debugger when you enable unmanaged code debugging. Look at the Call Stack window and note the [Native to Managed Transition] and [Managed to Native Transition] annotations. That's the debugger recognizing those cookies. Important for it as well since it needs to know whether or not the Locals window can display anything meaningful. The stack walk is also exposed in the framework, note the StackTrace and StackFrame classes. And it is very important for sandboxing, Code Access Security (CAS) performs stack walks.

这篇关于压缩发生后GC如何更新引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆