C# 和 Java 中的垃圾回收之间的根本区别是什么?

2022-09-01 12:14:14

我最近从一位“高级”开发人员/同事那里得到了一些关于C#垃圾收集器的非常错误的建议,例如......

  • “你需要在C#的任何地方使用析构函数,因为垃圾回收器是无法依赖的。

  • “C#垃圾回收器不能像Java垃圾回收器那样被认为是这样的”。

这对我来说听起来非常可疑,据我所知,C#和Java垃圾回收器之间的区别如下......

  • C# 是一代垃圾回收器,Java 在 1.6 中是并发标记扫描,G1 是具有 Java 7 的新的默认(分代)垃圾回收器,并且自 ~1.6.21 以来一直是可选的。据我所知
  • C# 作为一种语言,能够手动释放实现 的对象。Java 必须始终使用垃圾回收,尽管某些框架(如 SWT)要求您手动调用方法来释放底层本机代码中的内存。IDisposable

我意识到Java和C#只是语言,垃圾回收器是运行时的一个组件,但是在这种情况下,我特别谈到了Sun / Oracle JVM和Microsoft .NET Runtime。

有人有反馈吗?


答案 1

从广义上讲,你得到的建议是一堆胡言乱语。

C# 和 Java 都有 GC,试图优化大量小对象的快速恢复。它们旨在解决相同的问题,它们以略微不同的方式进行,但作为用户,您使用它们的方法的技术差异很小,对于大多数用户来说甚至不存在。

IDisposable与GC本身无关。这是命名方法的标准方式,否则将称为 、 、 等,在 Java 中通常称为 。有人建议Java 7添加与关键字非常相似的东西,该关键字将调用类似的方法。closedestroydisposeusingclose

C#中的“析构函数”指的是终结器 - 这是故意这样做的,以混淆程序员C++。:)CLR 规范本身调用它们终结器,就像 JVM 一样。

Java 和 C#/CLR 在很多方面(用户值类型、属性、泛型和称为 Linq 的整个相关功能系列)有很多不同之处,但 GC 是一个领域,您可以在其中开发大量软件,而无需担心它们之间的差异。


答案 2

他在破坏者上倒退。除非至关重要,否则不需要在 C# 中使用析构函数。如果您确实使用它们,则应该调用 SuppressFinalize(),如果您知道该对象处于不再需要析构函数代码的状态(最常见的是因为在调用 IDisposable.Dispose() 时发生了相同的清理)。如果一个对象有一个析构函数,并且尚未调用 SuppressFinalize,那么它将存活更长时间(以便它可以调用该析构函数)。

垃圾回收器肯定是可以信赖的。不能依靠它来调用析构函数,或者在一定时间内这样做,但这并不是它不可靠的问题,而是它在收集垃圾方面是否可靠的问题,这是它的工作!

我对Java垃圾收集器知之甚少,我毫不怀疑他说得对,当你深入到更精细的细节时,它们不能被认为是彼此一样的,尽管我希望为了Java程序员的缘故,它可以被认为是像.NET一样大多数时候 - 也就是说根本不想它, 一般来说,你不必这样做。