有谁知道Java和.Net垃圾收集器之间的主要区别?网络搜索没有透露太多,这是一个测试中出现的问题.
区别在于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集合可能不会导致完全停顿)以及作为预先采用的方法,试图避免将某些分配放入伊甸园生成.
这只是为了增加ShuggyCoUk的优秀答案..NET GC还使用了所谓的大对象堆(LOH).CLR在LOH上预分配了一堆对象,并且在LOH上也分配了至少85000字节的所有用户分配对象.此外,double[]
由于一些内部优化,在LOH上也分配了1000个或更多元素.
LOH的处理方式与代际堆的处理方式不同:
它只在完全收集期间进行清洁,并且永远不会像世代堆那样被压缩.
来自LOH的分配是通过自由列表完成的,就像malloc
在C运行时中处理的那样,而来自世代堆的分配基本上是通过在第0代中移动指针来完成的.
我不知道JVM是否有类似的东西,但它是关于如何在.NET中处理内存的基本信息,所以希望你发现它很有用.
如果我没记错的话,JVM不会像CLR那样将解除分配的内存释放回操作系统.