当前位置: 欣欣网 > 码农

.NET中的内存管理和垃圾回收,优秀码农必备

2024-06-19码农

内存管理和垃圾回收是 .NET 开发的基本方面,对于构建高效且可伸缩的软件应用程序非常重要。在这篇文章中,我们将讨论堆栈和堆内存,探索内存分配机制,并了解 .NET 中的垃圾回收。

了解堆栈和堆内存

堆栈内存

堆栈是用于执行程序代码和存储方法调用帧、局部变量和函数参数的内存区域。堆栈上的内存以后进先出 (LIFO) 方式进行管理。

voidExampleMethod()
{
int localVar = 10; // Local variable stored on the stack
}

在这里,变量存储在堆栈上,当方法退出时,其内存会自动释放。localVarExampleMethod

堆内存

堆是用于动态分配内存(如对象和数组)的内存区域。堆上的内存由垃圾回收器手动或自动管理。

classMy class
{
publicint MyProperty { get; set; }
}
voidExampleMethod()
{
My class obj = newMy class(); // Object allocated on the heap
obj.MyProperty = 20;
}

在这里,对象存储在堆上,其内存由垃圾回收器管理。obj

.NET 中的内存分配

值类型与引用类型

在 .NET 中,类型被分类为值类型或引用类型。值类型存储在堆栈中,而引用类型存储在堆中,对它们的引用存储在堆栈中。

voidExampleMethod()
{
intvalue = 10; // Value type stored on the stack
My class reference = newMy class(); // Reference type stored on the heap
}

.NET 中的垃圾回收

垃圾回收基础知识

垃圾回收是自动回收不再使用的对象占用的内存的过程。.NET 采用分代垃圾回收方法,其中对象根据其年龄划分为几代。

classProgram
{
staticvoidMain()
{
My class obj = newMy class();
// Code using 'obj'
// When 'obj' is no longer referenced, it becomes eligible for garbage collection
}
}

垃圾回收会定期发生,或者当系统确定堆内存不足时发生。在垃圾回收期间,垃圾回收器遍历所有活动引用,标记可访问对象,并为无法访问的对象解除内存分配。

垃圾回收中的几代人

.NET 利用三代进行垃圾回收:第 0 代、第 1 代和第 2 代。对象从第 0 代开始,并根据其生存情况晋升到更高世代。

  • **第 0 代(第 0 代):**这是最年轻的一代,包含短暂的物体。内存分配从这里开始。垃圾回收器在此代中频繁运行,以快速从不再需要的对象中回收内存。收集 Gen 0 通常非常快,因为它涉及的对象较少。

  • **第 1 代(第 1 代):**在第 0 代垃圾回收中幸存下来的对象将提升为第 1 代。这一代充当短寿命和长寿命对象之间的缓冲区。收集第 1 代的频率低于第 0 代,但仍旨在有效地回收内存。

  • **第 2 代(第 2 代):**此生成包含长期存在的对象,例如静态数据和长时间使用的对象。就性能而言,收集第 2 代是最昂贵的,因为它涉及堆的更大一部分。因此,这一代垃圾回收器的运行频率较低。

  • Generational Collection 的工作原理

  • **对象推广:**当对象在其当前一代的垃圾回收中幸存下来时,它将提升到下一代。例如,Gen 0 中在集合中幸存下来的对象将移动到 Gen 1。

  • **世代扫描:**垃圾收集器对不同的世代执行不同类型的清扫。Gen 0 集合是次要集合,而 Gen 2 集合是涉及更全面的内存管理任务的主要集合。

  • 让我们考虑一个例子,看看对象是如何在几代人之间移动的。

    usingSystem;
    classProgram
    {
    staticvoidMain()
    {
    // Create object in Generation 0
    My class obj1 = newMy class();
    // Perform some operations
    DoWork();
    // Force a Gen 0 garbage collection
    GC.Collect(0); // Collects Generation 0
    Console.WriteLine("Gen 0 collection completed.");
    // Create more objects
    My class obj2 = newMy class();
    // Perform some more operations
    DoMoreWork();
    // Force a Gen 1 garbage collection
    GC.Collect(1); // Collects Generation 1 and Generation 0
    Console.WriteLine("Gen 1 collection completed.");
    // Create long-lived object
    My class obj3 = newMy class();
    // Simulate application running
    RunApplication();
    // Force a Gen 2 garbage collection
    GC.Collect(2); // Collects Generation 2, Generation 1, and Generation 0
    Console.WriteLine("Gen 2 collection completed.");
    }
    staticvoidDoWork()
    {
    // Allocate some temporary objects
    for (int i = 0; i < 100; i++)
    {
    My class tempObj = newMy class();
    }
    }
    staticvoidDoMoreWork()
    {
    // Allocate more temporary objects
    for (int i = 0; i < 100; i++)
    {
    My class tempObj = newMy class();
    }
    }
    staticvoidRunApplication()
    {
    // Simulate long-running operations
    for (int i = 0; i < 1000; i++)
    {
    My class tempObj = newMy class();
    }
    }
    }
    classMy class
    {
    publicint MyProperty { get; set; }
    }











    使用分代垃圾回收的最佳实践

    1. **最小化长期对象:**设计应用程序以最大程度地减少长期对象的数量。这降低了第 2 代收集的频率和成本。

    2. **正确处理对象:**实现接口和use语句,确保及时释放非托管资源。IDisposableusing

    3. **避免大型对象分配:**大型对象直接分配在大型对象堆 (LOH) 中,并在第 2 代收集期间收集。最大程度地减少大型对象分配,以减少对第 2 代集合的影响。

    classResourceHolder : IDisposable
    {
    privatebool disposed = false;
    publicvoidUseResource()
    {
    if (disposed)
    {
    thrownewObjectDisposedException("ResourceHolder");
    }
    // Use the resource
    }
    publicvoidDispose()
    {
    Dispose(true);
    GC.SuppressFinalize(this);
    }
    protectedvirtualvoidDispose(bool disposing)
    {
    if (!disposed)
    {
    if (disposing)
    {
    // Release managed resources
    }
    // Release unmanaged resources
    disposed = true;
    }
    }
    ~ResourceHolder()
    {
    Dispose(false);
    }
    }



    内存管理和垃圾回收是 .NET 开发的重要组成部分,会影响应用程序性能和可伸缩性。通过应用最佳实践,我们可以优化内存使用、提高应用程序性能并构建高效的 .NET 应用程序。通过这篇文章,我们探讨了 .NET 中的内存管理和垃圾回收。

    如果你喜欢我的文章,请给我一个赞!谢谢