• 【C#】CLR内存那点事(高级)


    对于这篇,不想再对值类型进行讨论,如要看值类型的内存怎么玩可以看一下(CLR内存那点事 初级),我们这篇主要讨论一下引用类型。

    先来装备两个类

     internal class Employee
        {
            public static Employee LookUp(string name)
            {
                return null;
            }
    
            public virtual string GetProgressReport()
            {
                return string.Empty;
            }
        }
    
        internal class Manager : Employee
        {
            public override string GetProgressReport()
            {
                return string.Empty;
            }
        }

    Employee类里有一个虚方法GetProgressReport和一个静态方法LookUp,Manager类继承了Employee并重写了GetProgressReport.

         static void Main(string[] args)
            {
                Employee e = new Manager();
                e = e.LookUp("Tom");
                e.GetProgressReport();
            }

     我们在Main里面写上这样的代码,来看看栈和堆是怎么运作的。

    当JIT编译器将这些IL代码转换成本地CPU指令时,会注意到所有的类型:Employee,Manager,String(由于Tom字符串).

    1.当运行方法之前,"prologue"代码会为这些对象在内存中开辟空间。

    2.Employee e=new Manager();会把e压入栈,然后保存Manager对象地址,我们在初级篇的时候说过,每个对象都有一个同步块索引和类型对象指针,这个指针就说存的地址。

    3.e=Employee.LookUp("Tom");调用一个静态方法时,CLR会定位与定义静态方法的类型对应的类型对象。然后JIT编译器在类型对象的方法表中查找与被调用的方法对应的记录项,对方法进行JIT编译(如果需要的话),再调用JIT编译的代码。这个时候我们知道LoopUp返回的是Employee对象(这时,我一开始创建的Manager对象还不确认有没有被清除,因为GC会自动去清理这些托管代码),所以在堆上面开辟一个Employee的内存块并把e的地址改变成Employee对象所在的位置。

    注意:Employee和Manager类型对象都包含了”类型指针对象“成员。这时由于类型对象本质上也是对象。CLR创建类型对象时,必须初始化这些成员。初始化成什么呢?CLR开始在一个进程中运行时,会立即为MSCorLib.dll中定义的System.Type类型创建一个特殊的类型对象。Employee和Manager类型对象都是该类型的”实例“。 因此,它们的类型对象指针成员会初始化成对System.Type类型对象的引用。

    顺便说一句Object.GetType返回的就说”类型指针对象“所存储的地址。

  • 相关阅读:
    AES密码算法详解(转自https://www.cnblogs.com/luop/p/4334160.html)
    快速排序和插入排序——我的代码
    北京大学1001ACM——高精度类型题总结
    C语言数组不知道输入几个整数以及输入一直到为0
    C语言并查集例子——图问题巧用parent[]数组
    C语言快速判断素数——不超时
    C语言如何才能使用bool类型
    C语言两个特别大的整数类型相加超出范围使用两个技巧
    C语言存30位数字长的十进制方法
    dockerfile相关命令
  • 原文地址:https://www.cnblogs.com/guochenkai/p/3884991.html
Copyright © 2020-2023  润新知