GC.Collect如何影响垃圾回收 推荐
2013-12-19 23:50
323 查看
根据垃圾回收的算法,对象在内存中是按代的方式存放的,通常情况下,当第0代沾满分配的空间的时候(比如是256k),GC就会启动去回收第0代对象,幸存的第0代对象会被放入第1代中去,第1代的对象要等到放满了才会收集,因此,越是年轻的代越是被频繁的收集,由于通常情况下GC只收集第0代对象,既保证了可回收较多的内存,又忽略了老一代的对象,从而加快了垃圾回收的速度,提升了性能。
因此当调用gc.collect的时候,相当于强制的对所有代,不管年轻还是老的都执行一次回收。由于垃圾回收器在回收的资源的时候,正在执行托管代码的线程都会被挂起,具体的细节相当复杂,因为有的线程运行在不安全的点,CLR不能执行垃圾回收,因此CLR会采用线程劫持技术,即通过修改线程栈的方法,来做垃圾回收。这种复杂性使得性能降低。除非确定大量的旧对象死亡,才考虑调用这个方法。
所以,在一般情况下,尽量不要干预垃圾回收器工作,即尽量避免主动调用GC.Collect。
由于垃圾回收是异步的,CLR有一个专用的线程负责垃圾回收,因此,即使调用GC.Collect,也并不是实时的调用了Finalize,因此要保证确实调用了析构方法,可以使用语句GC.WaitForPendingFinalizers()。
下面是一段代码,通过注释掉
GC.Collect();
GC.WaitForPendingFinalizers();
语句,看出端倪。
但是当取消注释后,由于强制垃圾回收时,aa1对象和aa2对象都是null,因此就把它们回收掉了。顺序就是213了。
注意,如果aa1和aa2不设成null,那么强制回收时,并不认为这2个对象可以回收。因此还是会等到进程结束的时候才会回收。
因此当调用gc.collect的时候,相当于强制的对所有代,不管年轻还是老的都执行一次回收。由于垃圾回收器在回收的资源的时候,正在执行托管代码的线程都会被挂起,具体的细节相当复杂,因为有的线程运行在不安全的点,CLR不能执行垃圾回收,因此CLR会采用线程劫持技术,即通过修改线程栈的方法,来做垃圾回收。这种复杂性使得性能降低。除非确定大量的旧对象死亡,才考虑调用这个方法。
所以,在一般情况下,尽量不要干预垃圾回收器工作,即尽量避免主动调用GC.Collect。
由于垃圾回收是异步的,CLR有一个专用的线程负责垃圾回收,因此,即使调用GC.Collect,也并不是实时的调用了Finalize,因此要保证确实调用了析构方法,可以使用语句GC.WaitForPendingFinalizers()。
下面是一段代码,通过注释掉
GC.Collect();
GC.WaitForPendingFinalizers();
语句,看出端倪。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; using System.Reflection; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { AA aa1 = new AA("1"); AA aa2 = new AA("2"); AA aa3 = new AA("3"); aa1 = null; aa2 = null; //GC.Collect(); //GC.WaitForPendingFinalizers(); var tmp = aa3; } } public class AA { public string id = ""; public AA(string s) { id = s; Console.WriteLine("对象AA_" + s + "被创建了"); } ~AA() { Console.WriteLine(id + " 析构函数被执行了"); } } }当语句被注释掉的时候,虽然aa1和aa2都设成了null,但是垃圾回收并不是马上就把它们回收掉。对象可能都被放在第0代上,等进程结束的时候,由垃圾回收器一起回收。所以输出如下,顺序是321
但是当取消注释后,由于强制垃圾回收时,aa1对象和aa2对象都是null,因此就把它们回收掉了。顺序就是213了。
注意,如果aa1和aa2不设成null,那么强制回收时,并不认为这2个对象可以回收。因此还是会等到进程结束的时候才会回收。
相关文章推荐
- 成为Java GC专家(6):JDBC连接池如何影响垃圾回收
- 成为Java GC专家(6):JDBC连接池如何影响垃圾回收
- 成为Java GC专家(6):JDBC连接池如何影响垃圾回收
- GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?
- Java GC系列(2):Java垃圾回收是如何工作的?
- 《JVM垃圾回收相关内容》开发中,如何尽量减少GC开销,减轻垃圾回收的负担
- 成为JavaGC专家(2)—如何监控Java垃圾回收机制
- Java GC系列(2):Java垃圾回收是如何工作的?
- GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?
- SSCLI中GC垃圾回收源码分析(3) - GarbageCollectGeneration()与SuspendEE
- 垃圾回收机制GC知识总结兼谈如何用好GC
- 成为Java GC专家(2):如何监控Java垃圾回收机制
- Java GC系列(2):Java垃圾回收是如何工作的?
- 成为JavaGC专家Part II — 如何监控Java垃圾回收机制
- System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接
- Android开发之浅谈垃圾回收机制GC以及如何用好GC
- 成为Java GC专家(3)—如何优化Java垃圾回收机制
- 成为Java GC专家(3)—如何优化Java垃圾回收机制
- 成为Java GC专家系列(3) — 如何优化Java垃圾回收机制
- 如何降低90%Java垃圾回收时间?以阿里HBase的GC优化实践为例