C#垃圾回收

  1.   CLR垃圾回收器采用代(generation)机制,目前支持0、1、2三代:
    • 新构造添加到堆的对象称为第0代。
    • 经过对第0代的垃圾回收之后,第0代的幸存者被提升至第1代。
    • 经过对第1代的垃圾回收之后,第一代的幸存者被提升至第2代
    • CLR初始化时,会为每一代选择预算。第0代的预算约为256K,第1代预算约2M,第2代预算约10M。在实际使用过程中,垃圾回收器会用类似启发式算法调整各代的预算。
  2. 软件开始运行时,运行时会为每一个Generation预留一块连续的内存(这样说并不严格,但不影响此问题的描述),同时会保持一个指向此内存区域中尚未使用部分的指针P,当需要为对象分配空间时,直接返回P所在的地址,并将P做相应的调整即可

  3. .NET会将对象分成两种情况区别对象,一种是大小小于85000字节的对象,称之为小对象,它就对应于前面描述的一般情况;另外一种是大小在85000之上的对象,称之为大对象。在.NET中,所有大对象都是分配在另外一个特别的连续内存(LOH, Large Object Heap)中的,而且,每个大对象在创建时即属于G2,也就是说只有在进行Generation 2的垃圾回收时,才会处理LOH。而且在对LOH进行垃圾回收时不会压缩内存!更进一步,LOH上空间的使用方式也很特殊——当分配一个大对象时,运行时会优先尝试在LOH的尾部进行分配,如果尾部空间不足,就会尝试向操作系统请求更多的内存空间,只有在这一步也失败时,才会重新搜索之前无效对象留下的内存空隙

  4. 对象被标示为垃圾后会自动调用其Finalize方法,前提是对象重写了object的Finalize方法
  5. GC.SuppressFinalize是说在垃圾回收的时候不执行这个对象的C#析构函数中的内容。

  6. Dispose()方法和Close()方法的区别:
    • Dispose()方法除了释放资源之外,还会通知垃圾收集器对该对象不再需要执行终结操作(析构函数),它是通过调用GC.SuppressFinalize()方法来实现的,该方法通知垃圾回收器不在执行析构函数
    • Close()方法一般不会这么处理,因此在调用了Close()方法的对象,依然会停留在终结队列中,即对象会被清除。因此,我们应该优先调用Dispose()方法。
    • Dispose()方法不会将对象从内存上删除,它只是让对象释放非托管资源,这意味着如果释放的是仍被使用的对象,那么可能会遇到一些问题,因此,我们不应该释放那些仍然被程序其他地方引用的对象。
时间: 2024-12-11 18:47:58

C#垃圾回收的相关文章

Java垃圾回收原理(2)

Java虚拟机采用一种自适应的垃圾回收技术.依据的思想:对任何"活"的对象,一定能最终追溯到其存活在堆栈或静态存储区之中的引用.这个引用链条可能会穿过数个对象层次.由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有活的对象.对于发现的每个引用,必须追踪它所引用的对象,然后是此对象所包含的所有的引用,如此反复进行,直到"根源于堆栈和静态存储区的引用"所形成的网络全部被访问为止.至于如何处理找到存活的对象,取决于不同的Java虚拟机的实现.有一种名为停止-复

Java性能优化之JVM GC(垃圾回收机制)

Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.stop-the-world 意味着JVM因为需要执行GC而停止了应用程序的执行.当stop-the-world 发生时,除GC所需的线程外,所有的线程都进入等待状态,直到GC任务完成.GC优化很多时候就是减少stop-the-world 的发生. JVM GC回收哪个区域内的垃圾? 需要注意的是,JV

JavaGC专家(1)—深入浅出Java垃圾回收机制

在学习GC之前,你首先应该记住一个单词:"stop-the-world".Stop-the-world会在任何一种GC算法中发生.Stop-the-world意味着 JVM 因为要执行GC而停止了应用程序的执行.当Stop-the-world发生时,除了GC所需的线程以外,所有线程都处于等待状态,直到GC任务完成.GC优化很多时候就是指减少Stop-the-world发生的时间. 按代的垃圾回收机制 在Java程序中不能显式地分配和注销内存.有些人把相关的对象设置为null或者调用Sy

CMS垃圾回收机制

详解CMS垃圾回收机制 原创不易,未经允许,不得转载~~~ 什么是CMS? Concurrent Mark Sweep. 看名字就知道,CMS是一款并发.使用标记-清除算法的gc. CMS是针对老年代进行回收的GC. CMS有什么用? CMS以获取最小停顿时间为目的. 在一些对响应时间有很高要求的应用或网站中,用户程序不能有长时间的停顿,CMS 可以用于此场景. CMS如何执行?  总体来说CMS的执行过程可以分为以下几个阶段: 3.1 初始标记(STW) 3.2 并发标记 3.3 并发预清理

JVM那些事儿(二)——垃圾回收

这节小汪介绍一下jvm的垃圾回收机制,首先我们先提问: 1.为什么要有不同的垃圾算法 2.垃圾回收器要解决的终极目的是什么 3.小汪该如何选择自己的垃圾回收器 一.垃圾回收算法 众所周知,java堆内存的垃圾回收由java虚拟机管理,目前java有几种算法用来解决垃圾回收(以下只介绍最重要的两个算法) 1.1 复制算法 如图所示,复制算法可以说是最直观最简洁的算法了.按照复制算法的思路,内存要分为两块 Eden Survivor区域,Eden有一个,Survivor有两个. 首先,各种对象都在E

终结处理和垃圾回收(1)

之前一直不了解Java的垃圾回收原理,最近看了Java编程思想,有点想法,做做笔记. 首先,我们都了解初始化的重要性,但是常常会忘记同样也重要的清理工作.Java有垃圾回收器负责回收无用对象占用的内存资源.但是也有特殊情况:假定你的对象(并非使用new)获得一块"特殊"的内存区域,由于垃圾回收器只知道释放那些经由new分配的内存,所以它不知道如何释放该对象的这块特殊内存.为了应对这种情况,Java允许在类中定义一个名为finalize()方法. Java的finalize()不同于C+

Java 垃圾回收机制(早期版本)

Java 垃圾回收机制在我们普通理解来看,应该视为一种低优先级的后台进程来实现的,其实早期版本的Java虚拟机并非以这种方式实现的. 先从一种很简单的垃圾回收方式开始. 引用计数 引用计数是一种简单但是速度很慢的垃圾回收技术. 每个对象都含有要给引用计数器,当有引用连接至对象时,引用计数+1. 当引用离开作用域或者被置为null时,引用计数-1. 当发现某个对象的引用计数为0时,就释放其占用的空间.   这种方法开销在整个程序生命周期中持续发生,并且该方法有个缺陷,如果对象之间存在循环引用,可能

Python中的垃圾回收机制

当我们声明一个对象的时候,例如str="abcdef",当我们不再使用str这个对象的时候,这个对象就是一个脏对象,垃圾对象,但是它还在占着内存,毕竟我们的电脑内存有限,所以应该有一个机制来回收它以及类似的对象.现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式.自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患. 对于一个字符串.列表.类甚至数值都是对象,且定位简单易用的语言,自然不会

JVM垃圾回收2(垃圾收集算法)

根据<深入理解java虚拟机>这本书总结 一.关于几个概念:(标记垃圾算法.垃圾收集算法.垃圾收集器) 前面说了如何寻找jvm垃圾,有两种方法:引用计数法/可达性算法.这篇准备讲,标记完垃圾之后,回收的算法,这里的算法只是垃圾回收的思想.后面会讲到多种垃圾收集器,这里的垃圾收集器就是运用了垃圾手机算法的思想,可以说是具体实现. 这里还是想多余的说一下这三个概念: 垃圾标记算法:标记垃圾的方法 垃圾收集算法:一种回收思想,供垃圾收集器使用.可能用在年轻代,也可能用在老年代(当然现在来说老年代和年

深入理解JAVA虚拟机之JVM性能篇---垃圾回收

一.基本垃圾回收算法 1. 按基本回收策略分 1) 引用计数(Reference Counting)  对象增加一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此算法最致命的是无法处理循环引用的问题. 2)标记-清除(Mark-Sweep)  执行分两阶段.第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除. 缺点是此算法需要暂停整个应用,同时会产生内存碎片. 3)复制(Copying) 把内存空间划为两个相等的区域,每