相同点:

都采用了分代的机制。

都支持并发GC。

都没有采用引用计数方式,而是采用了追踪技术。

.NET中,可以通过代码GC.Collect() 强制要求CLR进行垃圾回收(由于垃圾回收是异步的,CLR有一个专用的线程负责垃圾回收,因此,即使调用GC.Collect,也并不是实时的调用了Finalize,因此要保证确实调用了析构方法,可以使用语句GC.WaitForPendingFinalizers()来确保析构方法真的被运行了,参考

Java中也可以通过System.gc() 强制要求进行垃圾回收。(事实上也仅仅是建议JVM执行垃圾回收,JVM并不一定立即做回收行为。)      

       

不同点:

CLR预留了一块大空间,称作large object heap (LOH),目的是当有大对象(超过85000字节的)需要分配空间时,就可以放在这里。

这块地方和分代机制的不同之处在于,这个地方只有当发生full GC的时候,才会回收,而且这块地方不会被压缩。

Java中可以通过配置参数,使得大对象(大于设定的阈值)直接进入老年代(避免在年轻代上做大量的复制操作)。

JVM回收的内存的,仅仅在某些条件下才返回给操作系统。(详见:

.NET回收的内存,直接给返还给操作系统。

JVM在的垃圾回收机制,提供了大量的可配置参数。

而CLR的垃圾回收机制几乎没什么可以配置的(仅有的配置似乎就是工作站模式(Workstation)和服务器模式(Server))。

都支持并发GC。JAVA是在老年代上支持并发GC,采用的CMS收集器。

.NET的并发GC只在第2代上,并且在工作站模式下才会有。    

      

Java分成年轻代,老年代,永久代。

.NET分第0代,第1代,第2代。

.NET中采用了标记,压缩的方式。

JAVA由于收集器很多,因此不限于一种算法。

             

年轻代

老年代

方式

Serial收集器

复制算法

             

单线程,stop the world

SerialOld收集器                  

             

标记整理算法

单线程,stop the world                  

ParNew收集器

复制算法

标记整理算法

多线程,stop the world

Parallel Scavenge收集器

复制算法                
           
多线程,stop the world               

CMS收集器

             

标记清除

单线程

G1收集器

复制

标记整理

             

   

Java垃圾回收的几篇文章

.NET垃圾回收的几篇文章