首页 > 解决方案 > 内部最终对象(Java)上可能存在内存泄漏

问题描述

我对这些场合进行了一些搜索,但找不到令人满意的答案,所以我来了。注意:这将是一个示例代码,因为我不能发布原始代码中的任何内容,因为它是分类的。

假设这个场合:

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.
    }
}

让我们解释一下变量和类:

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

有什么建议么?谢谢。

标签: javamemory-leaks

解决方案


鉴于提供的代码,没有内存泄漏,因为someObject它存在final或不存在。实例只在范围内使用myMethod,对外没有给出引用(至少在范围外Instance)。那就是 GC 会注意到它可以myMethod在异步makeCall完成之后被收集。

我唯一担心的是您提到调用makeCall可能根本无法完成。您必须记住,在此调用完成之前,此调用上下文中的所有资源都将无法收集。那是 的实例InstanceClassMember并且SomeObject将在 的持续时间内保留在堆上makeCall

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

更新:

正如@Seelenvirtuose 指出的那样,您的示例代码可能有点过于简单,导致做出错误的假设。只要实例的Instance使用方式与它们在提供的代码中的使用方式相同,我的回答就是正确的——作为一次性对象。您必须知道,每次调用myMethod和调用classMember.addCallbackclassMember都会获得对在 中object创建的实例的引用myMethod。这是对object将累积的引用classMember,因此在相应的实例中Instance- 这就是我的添加的意思,至少在Instance. 鉴于提供的代码,您最终可能会出现内存泄漏。这完全取决于Instance您在现实世界场景中的使用情况。


推荐阅读