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

时间:2019-05-30 07:48:48

标签: java garbage-collection

在采访中,我遇到一个问题-“编写代码时如何帮助垃圾收集器?”。

我认为GC确实非常有效,我们不需要使用任何基本的良好代码实践,而是后来补充说,finally子句中的关闭资源可以肯定地帮助GC,但通常对此问题感到惊讶。

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

3 个答案:

答案 0 :(得分:2)

这个问题的措词很奇怪。 GC的工作不需要帮助。它可以在施加任何约束的情况下工作,或者如果无法满足约束则失败。

当然可以更改工作,但这并不是出于减轻GC负担的愿望而进行的-从事这项工作的人不是无聊的人-而是由于一些别有用心的动机,例如提高整体程序性能。

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

幼稚的代码可能更具可读性,但性能较低。如果您的目标是易于阅读的代码,那么执行复杂的优化以减少GC负担可能适得其反,因此“帮助GC”本身并不是目标。

现在,如果您的目标是改善某些性能指标,那么某些优化还涉及编写代码,以减少内存管理(分配+ GC)子系统完成的工作。一些可能的优化措施是避免终结器,发现内存泄漏,减少不必要的分配,避免庞大的Object []数组,调整GC参数,购买更好的硬件并减少对象寿命。适用哪种优化取决于应用程序,并且最好通过分析器,GC日志记录和相关的

找出来

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

因此,当您持有不再需要的对象实例的引用时,必须将其设置为null,以使垃圾收集器知道您不再对该实例感兴趣(以及它的后代)。

这并不意味着您在使用后必须将每个变量都设置为null,而是必须注意字段。 由于Java没有处理模式(有关更多信息,请参见here),因此您必须设计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相关的内存,因为它仍被{{1 }}。

这不好吗?这取决于MyClass2和MyClass1是否确实在做。

如果您知道MyClass2的寿命很长,并且想要保留对MyClass2的引用,但是要释放与MyClass1相关的内存,则必须执行类似于以下代码的操作:

m_MyReference

通过这种方式向调用者公开一种信号,表明您不再持有对不需要的实例的引用。

请记住,仅将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; } } 分配给变量或字段并不会自动释放内存。垃圾收集器是异步的,并在其决定时运行。 希望给出这个想法不要太深入。