.Net与Java垃圾收集器

时间:2009-01-29 18:00:27

标签: c# java garbage-collection

有谁知道Java和.Net垃圾收集器之间的主要区别?网络搜索没有透露太多,这是一个测试中出现的问题。

5 个答案:

答案 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的处理方式与代际堆的处理方式不同:

  • 只有在完全收集时才进行清洁,并且它永远不会像世代堆那样被压缩。
  • 来自LOH的分配是通过自由列表完成的,就像在{C}运行时处理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)

我发现了这个:

  

在J2SE平台版本1.4.2中,有四个垃圾收集器可供选择,但用户没有明确选择,总是选择串行垃圾收集器。在5.0版中,收集器的选择基于启动应用程序的机器的类。

here

  

同样正如JVM管理对象的破坏一样,CLR也通过Mark and Compact垃圾收集算法进行管理

here

我希望这会有所帮助......