前言


今天查看一个同事的代码,发现代码中多处地方使用了GC.Collect()方法,我问他为什么这么做,他说感觉程序中定义了好多变量,怕GC回收不及时,用GC.Collect()可以手动掌控GC进行垃圾回收。

先不说他对GC的垃圾回收机制还不了解,就是调用GC.Collect()后GC真的会不会回收这个问题都需要再深入了解一下。

GC.Collect


下面我们通过一个小例子,来看一下使用GC.Collect后的内存情况。

我们知道可以通过GCHandle设置引用类型(可直接复制到本机结构中的类型)在GC垃圾回收时不移动地址,并且获取地址值,那么就可以通过在两次地址获取中间加入Collect方法,来判断GC是否真的进行了垃圾回收。

using System;
using System.Runtime.InteropServices; namespace TestGCCollect
{
class Program
{
static void Main(string[] args)
{
//创建一个没有引用的垃圾对象
new object();
//这是我们要判定地址的对象
int[] gcTest = new int[]; //设定Pinned通知GC在进行回收的时候不移动地址
GCHandle gcHandle1 = GCHandle.Alloc(gcTest, GCHandleType.Pinned);
//获取gcTest在堆中的地址并输出
IntPtr add1 = gcHandle1.AddrOfPinnedObject();
Console.WriteLine(add1.ToString());
//通知GC当程序返回的时候可以回收
gcHandle1.Free(); //调用GC回收object垃圾
GC.Collect(); //再次获取地址
GCHandle gcHandle2 = GCHandle.Alloc(gcTest, GCHandleType.Pinned);
IntPtr add2 = gcHandle2.AddrOfPinnedObject();
Console.WriteLine(add2.ToString());
gcHandle2.Free(); Console.ReadKey();
}
}
}

我们发现地址并没有变化!

修改一下代码使用for循环生成多个object:

            //创建没有引用的垃圾对象
for (int i = ; i < ; i++)
new object();
//这是我们要判定地址的对象
int[] gcTest = new int[];

重新编译后,执行结果如下:

地址变了!

通过上面的代码,我们知道GC.Collect并不是只要执行就会进行垃圾回收,实际上GC会首先判断当前是不是真的需要进行回收,如果内存中只有很小的垃圾(碎片化不严重)时,这时候启动回收显然得不偿失,影响性能。

总结


1. 永远都不要手动进行GC.Collect操作。如果你认为有,需要检查你地代码

2. 即使当你手动进行垃圾回收时,GC还不会立即执行,它要先判断是否真正需要回收

最新文章

  1. Codeforces Round #284 (Div. 2)A B C 模拟 数学
  2. document.body.clientHeight 和 document.documentElement.clientHeight的区别
  3. 第一章 git指令与设置
  4. [Angularjs]单页应用之分页
  5. virtualenv -- python虚拟沙盒(linux版本)
  6. CPU相关信息
  7. PHP框架原理
  8. django入门教程(上)
  9. [国嵌攻略][103][Linux内核模块基础]
  10. awk 详解+实例
  11. Linux多线程实践(7) --多线程排序对比
  12. Chapter 5 Blood Type——31
  13. CF822D 贪心+递推
  14. Linux系统之常用文件搜索命令
  15. linux http配置
  16. 20165227 《Java程序设计》实验一(Java开发环境的熟悉)实验报告
  17. 20155305 2016-2017-2 《Java程序设计》实验二 Java面向对象程序设计
  18. WPF TextBox 获得焦点后,文本框中的文字全选中
  19. IPReversePathFilter
  20. VS 2013 with update安装失败(kb2829760)解决方案

热门文章

  1. Cocos2d-x获取随机数
  2. javaweb之javascript结合(三)
  3. 【HTML】Advanced1:Text: Time, Mark, and &quot;Presentational&quot;
  4. 【CSS】Intermediate1:Class and ID Selectors
  5. Sql-&gt;Linq-&gt; Lambda 相互转换
  6. bzoj 1226 [SDOI2009]学校食堂Dining(状压DP)
  7. 如何通过Visual Studio发布Azure应用程序
  8. redis命令之lrange
  9. sqlMetal用法和例子 自定义DBML
  10. win7下wubi安装Ubuntu,重装win7后找回Ubuntu启动项