• CLR 管理内存的区域


    CLR 管理内存的区域,主要有三块,分别为:

    线程的堆栈,用于分配值类型实例。堆栈主要由操作系统管理,而不受垃圾收集器的控制,当值类型实例所在方法结束时,其存储单位自动释放。栈的执行效率高,但存储容量有限。

    GC 堆,用于分配小对象实例。如果引用类型对象的实例大小小于 85000 字节,实例将被分配在 GC 堆上,当有内存分配或者回收时,垃圾收集器可能会对 GC 堆进行压缩

    LOH(Large Object Heap)堆,用于分配大对象实例。如果引用类型对象的实例大小不小于 85000 字节时,该实例将被分配到 LOH 堆上,而 LOH 堆不会被压缩,而且只在完全 GC 回收时被回收(85kb)

    IL 指令解析:

    newobj,用于创建引用类型对象。

    ldstr,用于创建 string 类型对象。

    newarr,用于分配新的数组对象。

    box,在值类型转换为引用类型对象时,将值类型字段拷贝到托管堆上发生的内存分配。

    内存分配:

    {

    栈上的内存分配

             实际上在方法调用时都会在栈中创建一个活动记录(包含参数、返回值地址和局部变量),并分配相应的内存空间,这种分配是一次性完成的。方法执行结束返回时,活动记录清空,内存被一次性解除。而数据的压栈和出栈是有顺序的,栈内是先进先出(FILO)的形式。具体而言:首先入栈的是返回地址;然后是参数,一般以由右向左的顺序入栈;最后是局部变量,依次入栈。方法执行之后,出栈的顺序正好相反,首先是局部变量,再是参数,最后是那个地址指针。

    }

    对于值类型来说,一般创建在线程的堆栈上。但并非所有的值类型都创建在线程的堆栈上,例如作为类的字段时,值类型作为实例成员的一部分也被创建在托管堆上;装箱发生时,值类型字段也会拷贝在托管堆上。

    对于分配在堆栈上的局部变量来说,操作系统维护着一个堆栈指针来指向下一个自由空间的地址,并且堆栈的内存地址是由高位到低位向下填充

    public static void Main()

            {

                int x = 100;

                char c = 'A';

            }

    假设线程栈的初始化地址为 50000,因此堆栈指针首先指向 50000 地址空间。代码由入口函数 Main 开始执行,首先进入作用域的是整型局部变量 x,它将在栈上分配 4Byte 的内存空间,因此堆栈指针向下移动 4 个字节,则值 100 将保存在 49997~50000 单位,而堆栈指针表示的下一个自由空间地址为49996

    接着进入下一行代码,将为字符型变量 c 分配 2Byte 的内存空间,堆栈指针向下移动 2 个字节至 49994 单位,值’A’会保存在 49995~49996 单位

    最后,执行到Main方法的右括号,方法体执行结束,变量 x和 c的作用域也随之结束,需要删除变量x和c 在堆栈内存中的值,其释放过程和分配过程刚好相反:首先删除 c 的内存,堆栈指针向上递增2个字节,然后删除 x的内存,堆栈指针继续向上递增 4个字节,程序执行结束。

    其他较复杂的分配过程,可能在作用域和分配大小上有所不同,但是基本过程大同小异。栈上的内存分配,效率较高,但是内存容量不大,同时变量的生存周期随着方法的结束而消亡

  • 相关阅读:
    阅读计划博文
    系统设计时所实现的质量属性战术
    关于如何提高系统的可用性和易用性
    jdbc.properties
    JDBCUtil
    软件质量属性的场景描述
    架构漫谈阅读笔记
    软件架构师工作过程
    orm框架中entityframework的 增删改查操作
    事件和委托
  • 原文地址:https://www.cnblogs.com/jiebian/p/3059389.html
Copyright © 2020-2023  润新知