class="Apple-style-span" style="margin: 0px; padding: 0px; font-weight: normal;">使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
堆栈不存在垃圾回收的问题, 直接压栈就可以了。
堆的话,需要复杂的垃圾回收机制。
垃圾回收是对堆来进行操作,堆中的对象是否有效, 是通过遍历堆栈来获取的, 就是一个引用计数的问题。
一个引用类型的实例化过程:
Class a = new Class();
1) Class a 的时候, 生成一个空的引用指针,并把他压栈到堆栈中。
2)new Class() 生成一个类的实例, 并且在堆上分配对应内存。
3 ) = 赋值的时候, a的引用指向新生成的实例。
问题原因:
系统变慢的一个很主要的原因就是,随着系统运行时间的增长, 内存碎片也会越来越多。就是因为程序反复在堆中创建和释入变量。久而久之,可用变量将不再是联系的内存空间。 为了寻址这些可用变量, 系统也会增加开销。
.NET 垃圾回收器实现机制:
垃圾回收器会压缩托管堆的内存空间, 是可用对象在一个连续的内存空间中,同时将堆栈中的引用变量的地址修改为新的地址。这样会带来一部分的系统开销。 但是内存整理后带来的性能提升远远大于压缩内存空间所消耗的性能消耗。
最大的好处就是: 开发者再也不用关心内存的泄露问题
垃圾回收的简单逻辑:
处理逻辑:
1)遍历Generation 0 Kill掉没用的对象,有用的升级到Generation 1
2).如果空间已经够用的话, 就不继续回收了 ,直接返回
3)如果空间还不够或者Generation 1 也满了, Kill掉G1中没用的对象,有用的升级到G2
4)如果有必要 继续回收G2...如果g2也不够了 那么就内存溢出了。
参数:
GC在初始化完成的时候Generation 0 的大小就确定为256k (优先考虑放在L2 Cache中)
Generation 1 开始大小是0 最大可以到2M
Generation 2 没有限制