内部最终对象(Java)上可能的内存泄漏

时间:2019-01-21 08:11:15

标签: java memory-leaks

我在这些场合进行了一些搜索,找不到满意的答案,所以我在这里。 注意:这将是示例代码,因为由于原始代码已被分类,因此我无法发布任何内容。

假设这种情况:

public class Instance
{
    private ClassMember classMember = new ClassMember();

    // Imagine this method is called once as like the main method of apps.
    public static void main(String[] args)
    {
        new Instance().myMethod();
    }

    private void myMethod()
    {
        final SomeObject object = new SomeObject();

        // This is the class member that is declared at top of the class.
        classMember.addCallback(new Callback()
        {
            @Override
            public void onCall(boolean result)
            {
                object.setResult(result).report(); // I'm done with this object, want to release it.

                // After this call, will there be a leak due to "SomeObject object"?
                // If so, how can this be prevented from happening?
            }
        });

        object.makeCall(classMember); // asynchronous task such as Internet connections.
    }
}

让我们解释变量和类:

  • 实例是包含main方法的假定主类。考虑此方法是从另一个类中调用的,此方法是为了简化而定义的。
  • ClassMember是处理Internet连接回调的类。将与 SomeObject 一起使用。
  • SomeObject是必须在方法中最终实例化的对象,才能在“ addCallback”方法中使用。 “ makeCall”方法是异步的,可能完成与否,例如建立Internet连接。

现在,我想知道的是,由于“最终SomeObject对象”,可能会发生内存泄漏,我想通过在“ onCall()”方法中收到回调后将其释放(例如将其设置为null)来释放它,以防止它泄漏。但是因为它是最终的,所以我不能这样做,因此我正在寻找替代方法。

有什么建议吗?谢谢。

2 个答案:

答案 0 :(得分:1)

鉴于提供的代码,没有someObjectfinal导致的内存泄漏。该实例仅在myMethod的范围内使用,并且未引用外部(至少在Instance之外)。也就是说,GC将注意到可以在myMethod或异步makeCall完成之后对其进行收集。

我唯一担心的是您提到对makeCall的调用可能根本无法完成。您必须记住,在调用完成之前,此调用上下文中的所有资源将无法收集。那就是InstanceClassMemberSomeObject的实例将在makeCall期间保留在堆上。

当然,如果您在makeCall中做一些愚蠢的事情,则会以一种或另一种方式泄漏。

更新

正如@Seelenvirtuose指出的那样,您的示例代码可能有点过分简化,导致做出错误的假设。我的答案是正确的,只要Instance的实例在提供的代码中的使用方式为一体即可。您必须知道,每次调用myMethod和每次调用classMember.addCallback时,classMember都会引用在object中创建的myMethod实例。也就是说,对object的引用将累积在classMember中,因此在Instance的相应实例中-这就是我至少在Instance < / em>。给定所提供的代码,您可能最终会遇到内存泄漏或没有内存泄漏的情况。这完全取决于您在现实情况中Instance的使用情况。

答案 1 :(得分:-1)

最终状态不会阻止它进行垃圾收集。如果执行了回调并且对象未保存在classMember中(由于某些处理程序列表或其他某种原因),则引用计数器将减少为0,因此将被垃圾回收(有时)。