com.android.internal.policy.impl.PhoneLayoutInflater有时会保留在内存中(hprof转储)

com.android.internal.policy.impl.PhoneLayoutInflater有时会保留在内存中(hprof转储),android,Android,我正在检查内存,试图通过hprof转储找到最终的内存泄漏 我发现,有时当我通过后退按钮离开一个活动(这将完成该活动)时,该活动仍会保留在内存中,但它只有两个GC根,虽然看起来不是很强 这是我的活动流程/我单击和测试的方式: A、 B,C是活动 1)A->B->(返回)A 2)执行hprof转储,结果如下: B仍在内存中,B活动的GC根中唯一的元素是: com.myapp.android.activity.directory.B com.android.internal.policy.impl.

我正在检查内存,试图通过hprof转储找到最终的内存泄漏

我发现,有时当我通过后退按钮离开一个活动(这将完成该活动)时,该活动仍会保留在内存中,但它只有两个GC根,虽然看起来不是很强

这是我的活动流程/我单击和测试的方式:

A、 B,C是活动

1)A->B->(返回)A

2)执行hprof转储,结果如下:

B仍在内存中,B活动的GC根中唯一的元素是:

com.myapp.android.activity.directory.B

  • com.android.internal.policy.impl.PhoneLayoutInflater的mContext

    • android.app.ContextImpl[Stack Local]的MlayoutFlater

      • java.lang.Thread[线程]“main”的[局部变量]
  • android.app.ContextImpl[Stack Local]的mOuterContext

    • java.lang.Thread[线程]“main”的[局部变量]
(线程“main”似乎是UI线程)

从以下位置继续:

3)A->C->(返回)A

4)执行hprof转储,结果如下(如预期):

B不再在内存中,C不再在内存中,只有A

现在我的问题是: 这个PhoneLayoutFlater是从哪里来的/为什么当我从B返回A时,它会保留在内存中,但在我进一步返回C并返回A之后它就会消失。

很明显,电话扩容器是为了增加浏览量,我知道它的目的。我只是不明白为什么它会通过主UI线程的GC根保存在内存中

当我检查上面列出的GC根时

java.lang.Thread的[局部变量] [线程]“主

它将具有以下特点:

  • com.myapp.android.activity.main的mUiThread。A[堆栈本地]
    • 。。。。
      • 这是android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper的$0[JNI Global]
我从A中调用活动B和C的方式是通过常规的
startActivity(intent)


为什么活动A的主UI线程会以某种方式与活动B关联和引用?

以下是我最后做的事情,但我仍然不满意我使用反射来解决这个问题。有人吗

public static boolean ReleaseActivityContext(Context context)
{                       
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);     
    Class<?> i = inflater.getClass();

    try 
    {    
        Field f = i.getSuperclass().getDeclaredField("mContext");
        f.setAccessible(true); // prevent IllegalAccessException
        f.set(inflater, null); // can cause IllegalAccessException
        return true;    
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }   
    return false;   
}
public静态布尔ReleaseActivityContext(上下文)
{                       
LayoutFlater充气器=(LayoutFlater)context.getSystemService(context.LAYOUT\u充气器\u服务);
i类=充气机。getClass();
尝试
{    
字段f=i.getSuperclass().getDeclaredField(“mContext”);
f、 setAccessible(true);//防止非法访问异常
f、 设置(充气机,null);//可能导致IllegaAccessException
返回true;
}
捕获(例外e)
{
e、 printStackTrace();
}   
返回false;
}

我也遇到了同样的问题,我使用Eclipse MAT分析hprof,花了8个多小时,最后我发现有一些简单的规则可以遵循

不要将长期引用保存到 上下文活动(对上下文的引用) 活动应该有同样的生命 循环(与活动本身相同)

尝试使用上下文应用程序 而不是上下文活动

避免在应用程序中使用非静态的内部类 如果你不能控制他们的行为 生命周期,使用静态内部类 并对 内部活动

遵循以下步骤:

然后单击。。。

您可以看到对象留在内存中的原因


现在修改你的代码,看看为什么有一些引用存在,而不需要它们存在。然后在后退键上按nullify这些引用和viola。世界将再次变得美丽:)

可能是相关的。感谢链接,但我已经读了很多次了。没有其他活动的UI线程的引用,我也是这样做的不知道“android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper[JNI Global]”的$0是从哪里来的。这是一件奇怪的事情。我对PhoneLayoutFlater也有同样的问题。过去我用反射来清除android中的这种内存异常(通常与列表相关)但我不知道这到底是什么原因,也不知道在不关闭我的应用程序的情况下,我能不能将反射设置为null。我打算给它增加一笔赏金。@MathiasLin,5年后(:你找到这个问题的原因了吗?我正在使用Eclipse MAT分析内存。Aizaz,谢谢你的帖子。我还没有时间尝试你发布的解决方案。它工作正常吗?据我所知,在我传递任何上下文时,没有活动上下文,只有应用上下文。顺便说一句,这里有一篇关于Android的关于内存的新博文分析:我正在使用yourkit.com进行mem分析,这也是一个很好的工具,但不是免费的。