【发布时间】:2010-10-04 07:26:33
【问题描述】:
有人知道 Java 和 .Net 垃圾收集器之间的主要区别吗?网络搜索并没有透露太多,这是一个测试中提出的问题。
【问题讨论】:
标签: c# java garbage-collection
有人知道 Java 和 .Net 垃圾收集器之间的主要区别吗?网络搜索并没有透露太多,这是一个测试中提出的问题。
【问题讨论】:
标签: c# java garbage-collection
区别在于 CLR (.Net) GC 和 JVM GC 而不是语言本身。 两者都可能发生变化,并且它们的行为规范松散,以便在不影响程序正确性的情况下进行更改。
存在一些历史差异,主要是由于 .Net 的设计借鉴了 java(和其他基于 gc 的平台)的演变。在下文中,不要假设 .Net 在某些方面优于它,因为它从一开始就包含功能,它只是后来出现的结果。
一个显着的公开可见的区别是 MS GC 暴露了它的代际性质(通过 GC api)这可能会在一段时间内保持正确,因为这是基于大多数程序表现出的行为的明显方法:大多数分配是非常短暂的。
最初的 JVM 没有分代垃圾收集器,尽管这个特性很快被添加了。
SunOracle 和其他人实现的第一代收集器往往是 Mark and Sweep。人们意识到标记-扫描-压缩方法将导致更好的内存局部性,从而证明额外的复制开销是合理的。 CLR 运行时以这种行为首次亮相。
SunOracle 和 Microsoft 的 GC 实施“精神”之间的区别之一是可配置性。
Sun 提供了大量选项(在命令行中)来调整 GC 的各个方面或在不同模式之间切换。许多选项都属于 -X 或 -XX 以表明它们缺乏跨不同版本或供应商的支持。相比之下,CLR 几乎没有提供可配置性。您唯一真正的选择是使用分别针对吞吐量和延迟进行优化的服务器或客户端收集器。
两家公司(以及开源实现中)都在积极研究 GC 策略) 以及 pre-tenuring 方法,它们试图避免将某些分配放入伊甸园生成。
【讨论】:
这只是为了补充 ShuggyCoUk 的出色答案。 .NET GC 还使用所谓的大对象堆 (LOH)。 CLR 在 LOH 上预分配了一堆对象,并且所有用户分配的至少 85000 字节的对象也都分配在 LOH 上。此外,由于一些内部优化,在 LOH 上分配了 1000 个或更多元素的 double[]。
LOH 的处理方式与分代堆不同:
malloc 一样,而来自世代堆的分配基本上是通过在第 0 代中移动一个指针来完成的。我不知道 JVM 是否有类似的东西,但它是关于如何在 .NET 中处理内存的基本信息,因此希望您会发现它有用。
【讨论】:
如果我没记错的话,JVM 不会像 CLR 那样将释放的内存释放回操作系统。
【讨论】:
Java 5 对其 GC 算法进行了很多更改。
我不是 C# 专家,但这两篇文章向我表明,它们都已经从简单的标记和扫描模式演变为新一代模型:
http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html http://www.csharphelp.com/archives2/archive297.html
【讨论】: