有谁知道Java和.Net垃圾收集器之间的主要区别?网络搜索没有透露太多,这是一个测试中出现的问题。
答案 0 :(得分:106)
区别在于CLR(.Net)GC和JVM GC,而不是语言本身。 两者都可能发生变化,其行为规范也会松散,以便在不影响程序正确性的情况下进行更改。
有一些历史差异很大程度上是由于.Net的设计与java(以及其他基于gc的平台)的演变。在下文中,不要假设.Net one在某种程度上是优越的,因为它从一开始就包含了功能,它只是后来的结果。
一个值得注意的公开可见差异是,MS GC暴露了它的世代性质(通过GC api),这可能会在一段时间内保持正确,因为根据大多数程序所表现的行为,这是一个明显的方法:大多数分配非常短暂。
虽然这个功能被迅速添加,但是初始JVM没有分代垃圾收集器。
由 Sun Oracle和其他人实施的第一代收藏家往往是Mark和Sweep。人们意识到,标记扫描紧凑的方法将导致更好的内存局部性,从而证明额外的复制开销。 CLR运行时首次出现此行为。
Sun 之间的区别Oracle和Microsoft的GC实现'ethos'是可配置性之一。
Sun 提供了大量选项(在命令行中)来调整GC的各个方面或在不同模式之间切换。许多选项都是-X或-XX,表明它们在不同版本或供应商中缺乏支持。相比之下,CLR几乎没有可配置性;您唯一真正的选择是使用服务器或客户端收集器,分别优化吞吐量和延迟。
GC战略的积极研究正在两家公司(以及开源实施)中进行。最近的GC实施中使用的当前方法是每个线程的eden区域(改善局部性并允许eden集合可能不会导致完全暂停)以及预先采用的方法,试图避免将某些分配放入伊甸园的产生。
答案 1 :(得分:29)
这只是为了增加ShuggyCoUk的优秀答案。 .NET GC还使用了所谓的大对象堆(LOH)。 CLR在LOH上预分配一堆对象,并且在LOH上也分配了至少85000字节的所有用户分配的对象。此外,由于一些内部优化,在LOH上也分配了1000个或更多元素的double[]
。
LOH的处理方式与代际堆的处理方式不同:
malloc
一样,而来自世代堆的分配基本上是通过在第0代移动指针来完成的。我不知道JVM是否有类似的东西,但它是关于如何在.NET中处理内存的基本信息,所以希望你发现它很有用。
答案 2 :(得分:19)
如果我没记错的话,JVM不会像CLR那样将解除分配的内存释放回操作系统。
答案 3 :(得分:3)
Java 5在其GC算法中引入了很多变化。
我不是C#maven,但这两篇文章告诉我,两者都已经从简单的标记和扫描演变为新一代模型:
http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html http://www.csharphelp.com/archives2/archive297.html
答案 4 :(得分:1)