如何编写代码来帮助垃圾收集器

在面试中我遇到了一个问题——“如何在编写代码时帮助垃圾收集器?”。

在我看来,GC 工作得非常好,我们不需要使用比基本的良好代码实践更多的东西,后来补充说,在 finally 子句中关闭资源肯定有助于 GC,但通常对这样的问题感到惊讶。

有好的回复吗?我们需要做一些不可思议的事情来帮助垃圾收集器吗?


犯罪嫌疑人X
浏览 136回答 3
3回答

海绵宝宝撒

垃圾收集器是一个“任务”,它定期扫描您的对象以检测未使用的对象(实际上它是一种模拟具有无限内存的机器的机制)。出于这个原因,当您持有对不再需要的对象实例的引用时,您必须将其设置为null以便让垃圾收集器知道您不再对该实例(可能还有它的后代)感兴趣。这并不意味着您必须null在使用后设置每个变量,但您必须注意字段。由于 Java 没有处置模式(有关更多信息,请参见此处),您必须设计 API 来模仿它:当您使用完包含要释放的引用的对象实例时,您必须添加适当的方法执行此类操作。考虑以下示例:class MyClass1{    int Field1;    int Field2;    int Field3;    int Field4;}class MyClass2{    private MyClass1 m_MyReference;    public MyClass2()    {        m_MyReference = new MyClass1();    }    public void DoSomething()    {        // do something here that uses m_MyReference.    }}如果 MyClass2 的一个实例被保留,但程序的其他一些可访问实例(例如,单例或当前在堆栈中的某个实例),您将永远不会释放与 MyClass1 关联的内存,因为它仍然被引用m_MyReference。这很糟糕吗?这取决于 MyClass2 和 MyClass1 真正在做什么。如果您知道 MyClass2 可能有很长的生命周期并且您希望保留对 MyClass2 的引用但要释放与 MyClass1 关联的内存,则必须执行类似于以下代码的操作:class MyClass2{    private MyClass1 m_MyReference;    public MyClass2()    {        m_MyReference = new MyClass1();    }    public void DoSomething()    {        // do something here that uses m_MyReference.    }    public void Dispose()    {        m_MyReference = null;    }}通过这种方式,您可以向调用者公开一种方式,表明您不再持有对您不需要的实例的引用。请记住,简单地分配null给一个变量或字段,不会自动释放内存。垃圾收集器是异步的,并在它决定时运行。希望在不深入的情况下给出这个想法。

烙印99

这个问题的措辞很奇怪。GC 的工作不需要帮助。它会在任何强加的约束条件下工作,如果不能满足约束条件,它就会失败。当然工作可以改变,但这并不是为了减轻 GC 的负担——它不是一个会厌倦其工作的人——而是出于一些不可告人的动机,比如改进整体程序表现。这些事情通常被定义为延迟、能耗、吞吐量或内存占用优化。但这些并不是程序员关心的唯一指标。简单性和代码可读性也很重要。朴素的代码可读性更强,但性能更差。如果您的目标是易于阅读的代码,那么执行减少 GC 负载的复杂优化可能会适得其反,因此“帮助 GC”本身并不是目标。现在,如果您的目标是提高某些性能指标,那么一些优化还涉及编写代码来减少内存管理(分配 + GC)子系统所做的工作。一些可能的优化包括避免终结器、发现内存泄漏、减少不必要的分配、避免庞大的 Object[] 数组、调整 GC 参数、购买更好的硬件和缩短对象的生命周期。哪种优化适用取决于应用程序,最好通过分析器、GC 日志记录和相关的工具来确定

天涯尽头无女友

垃圾收集器的工作非常高效灵巧,但我们可以通过将变量和对象指向 null 来增强其收集垃圾的能力,这些变量和对象不再被使用,也不再有对它们的引用。在文件处理期间使用close()和flush()方法。并且在线程处理中,在不使用时销毁线程。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java