1.前言 根对象被GC标记为存活对象,它是不会被回收的。那么它是如何释放的呢?本篇来看下
2.概述 示例代码:
static void Main(string[] args){
Program pm = new Program();
pm = null;
GC.Collect(0);//默认的GC垃圾回收器
Console.ReadLine();
}
pm为根对象,它的会一直被GC标记为存活。直到CLR整个运行结束,它依然是存活的。关于这一点,可以通过CLR Main入口的exit_code处断点观察。
int MAIN(const int argc, const char_t* argv[])
{
configuration config{};
if (!parse_args(argc, argv, config))
return EXIT_FAILURE;
if (config.self_test)
return self_test();
int exit_code = run(config);
return exit_code; //这个地方断点,基本上表示整个CLR运行完毕。
}
此时看下pm对象(注意这里的pm对象地址可以通过SuppressFinalize获取,或者是直接定位到托管Main函数头,在里面找到new汇编获取)的内存,pm指针:
0x0000029BDF334B38 00007ff7d0360168 0000000000000000
pm的MethodTable指针
0x00007FF7D0360168 0000001800100200 000000040007408c 00007ff7d0360000 00007ff7cff86110 00007ff7d030dc88
可以看到无论是pm还是mt都存在于内存当中,它为什么没有回收呢?需要了解下C/C++的分配方式
二:C/C++内存分配 模拟一段Object和MethodTable的分配:
#include<Windows.h>
#include<stdio.h>
class MethodTable{
public:
DWORD m_dwFlags;
DWORD m_BaseSize;
WORD m_wFlags2;
};
class Object{
public:
MethodTable m_pMethTab;
};
int main(){
//这种分配,系统自动回收,还有诸如:MethodTable mt;
//Main运行完成之后被系统自动回收。了解了解了这些,pm对象
//的object和methodtable是被系统自动回收的,所以它即使一直
//存活到CLR运行完毕,也会被回收。
MethodTable mt = (MethodTable());
mt.m_dwFlags = 1;
mt.m_BaseSize = 2;
mt.m_wFlags2 = 3;
MethodTable* mt1 = &mt;
Object ot = Object();
Object* ot1 = &ot;
ot.m_pMethTab = mt;
}
三:结论
托管根对象是在CLR运行完毕之后,被系统回收内存空间。