我正在检查内存,试图通过hprof转储找到最终的内存泄漏。
我发现有时候当我通过后退按钮(完成活动)离开活动时,活动仍会保留在内存中,但它只有两个GC根,这似乎不是很“强”虽然。
这是我的活动流程/我点击并测试的方式:
A,B,C是活动。
1)A - > B - > (返回)A
2)执行hprof转储,结果如下:
B仍然在内存中 ,B活动的GC根目录中唯一的元素是:
com.myapp.android.activity.directory.B
mContext of com.android.internal.policy.impl.PhoneLayoutInflater
android.app.ContextImpl的mLayoutInflater [Stack Local]
android.app.ContextImpl的mOuterContext [Stack Local]
(线程“main”似乎是UI线程)
继续A:
3)A - > C - > (返回)A
4)使用以下结果执行hprof转储(按预期方式):
B不再在内存中,C不再在内存中,只有A
现在我的问题是: 这个PhoneLayoutInflater来自哪里/为什么当我从B返回到A时它会留在内存中,但是在进一步转到C并返回到A后它会消失。
显然PhoneLayoutInflater用于膨胀视图,我知道它的目的。我只是不明白为什么它会通过主UI线程中的GC根目录保存在内存中。
当我检查上面列出的GC根
时java.lang.Thread的[局部变量] [主题]“主要
它将具有以下内容:
我从A调用活动B和C的方式是通过常规startActivity(intent)
为什么活动A的主UI线程会以某种方式与活动B相关联并被引用?
答案 0 :(得分:0)
这是我最终做的事情,但我仍然不满意我正在使用反射来解决这个问题。任何人??
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;
}
答案 1 :(得分:0)
我遇到了同样的问题,我使用Eclipse MAT来分析hprof,我花了8个多小时,最后我发现有一些简单的规则要遵循。
不要长期保持对a的引用 上下文活动(对...的引用) 活动应该有相同的生命 循环作为活动本身)
尝试使用context-application 而不是上下文活动。
避免使用非静态内部类 活动,如果你不控制他们的 生命周期,使用静态内部类 并提到一个弱的参考 里面的活动。
请按以下步骤操作:
然后点击......
你可以看到物体留在记忆中的原因
现在修改你的代码,看看为什么在不需要它们的情况下存在一些引用。然后在后面按键按下那些引用和中提琴..世界将再次看起来很漂亮:)