为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

犯罪嫌疑人X 2022-12-21 15:20:08
在面试中我遇到了一个问题——“如何在编写代码时帮助垃圾收集器?”。在我看来,GC 工作得非常好,我们不需要使用比基本的良好代码实践更多的东西,后来补充说,在 finally 子句中关闭资源肯定有助于 GC,但通常对这样的问题感到惊讶。有好的回复吗?我们需要做一些不可思议的事情来帮助垃圾收集器吗?
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

垃圾收集器是一个“任务”,它定期扫描您的对象以检测未使用的对象(实际上它是一种模拟具有无限内存的机器的机制)。


出于这个原因,当您持有对不再需要的对象实例的引用时,您必须将其设置为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给一个变量或字段,不会自动释放内存。垃圾收集器是异步的,并在它决定时运行。希望在不深入的情况下给出这个想法。


查看完整回答
反对 回复 2022-12-21
?
烙印99

TA贡献1829条经验 获得超13个赞

这个问题的措辞很奇怪。GC 的工作不需要帮助。它会在任何强加的约束条件下工作,如果不能满足约束条件,它就会失败。

当然工作可以改变,但这并不是为了减轻 GC 的负担——它不是一个会厌倦其工作的人——而是出于一些不可告人的动机,比如改进整体程序表现。

这些事情通常被定义为延迟、能耗、吞吐量或内存占用优化。但这些并不是程序员关心的唯一指标。简单性和代码可读性也很重要。

朴素的代码可读性更强,但性能更差。如果您的目标是易于阅读的代码,那么执行减少 GC 负载的复杂优化可能会适得其反,因此“帮助 GC”本身并不是目标。

现在,如果您的目标是提高某些性能指标,那么一些优化还涉及编写代码来减少内存管理(分配 + GC)子系统所做的工作。一些可能的优化包括避免终结器、发现内存泄漏、减少不必要的分配、避免庞大的 Object[] 数组、调整 GC 参数、购买更好的硬件和缩短对象的生命周期。哪种优化适用取决于应用程序,最好通过分析器、GC 日志记录和相关的工具来确定


查看完整回答
反对 回复 2022-12-21
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

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



查看完整回答
反对 回复 2022-12-21
  • 3 回答
  • 0 关注
  • 135 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信