我有两个Activity,都有一个内部类SurfaceView,它有一个内部类Thread。第一个是菜单屏幕,第二个是玩游戏的比赛屏幕。
要从第一个 Activity 开始第二个 Activity ,我这样做:
Intent intent = new Intent();
intent.setClass(Menu.this, RaceActivity.class);
intent.putExtra("level", level.getNumber());
startActivityForResult(intent, 0);
关卡完成后,从我运行的第二个 Activity 开始。
finish();
这会调用我的 onDestroy 方法。我的印象是这足以让我的第二个 Activity elligble 垃圾收集。但是当我完成比赛并多次开始新的比赛时,我发现我最终会撞车。在 Eclipse 中使用内存分析器工具 (MAT),我发现很多对我的第二个 Activity 的引用,并且 SurfaceView 和 Thread 仍然被保留。所以我也决定在 destroy 方法中清理它们。
public void onDestroy() {
super.onDestroy();
mPanel.mThread.destroy(); //destroys surfaceholder in thread
mPanel.mThread = null;
mPanel = null;
}
这似乎已经消除了几乎所有的东西。但是当我进入 MAT 时,我仍然看到一个对第二个 Activity 的引用(当选择路径到 GC 根时 -> 排除弱引用)
Class Name | Shallow Heap | Retained Heap
---------------------------------------------------------------------------
com.moz.by.RaceActivity @ 0x405b6108 Unknown| 280 | 8,008
---------------------------------------------------------------------------
这是我正在尝试进行 GC 的 Activity 的名称,因此它似乎在某处持有对其自身的引用。那个或 Unknown 关键字在这里具有一定的意义。
我对这个问题感到困惑,因为我不确定下一步该去哪里寻找这个问题。我想知道我是否能找到这个 Activity 最终清理的问题!现在已经坚持了几天,所以我想我会向你们好人彻底解释我的问题。有人可能会提出我可能犯的初学者错误。
感谢阅读。
附言这是我的第一个应用程序,如果我在我的工作流程中遗漏了一些基本的东西,我深表歉意。下面是我开始和结束几场比赛后来自 MAT 的 dominator_tree 的一部分。
Class Name | Shallow Heap | Retained Heap | Percentage
------------------------------------------------------------------------------------------------------------------
com.moz.by.RaceActivity @ 0x405989e8 Unknown | 280 | 4,464 | 0.15%
com.moz.by.RaceActivity @ 0x405b6108 Unknown | 280 | 8,008 | 0.26%
com.moz.by.RaceActivity @ 0x406532e8 Unknown | 280 | 4,024 | 0.13%
com.moz.by.RaceActivity @ 0x4077f290 Unknown | 280 | 5,440 | 0.18%
com.moz.by.RaceActivity$Panel @ 0x40513d40 Unknown | 432 | 1,496 | 0.05%
com.moz.by.RaceActivity$Panel @ 0x40527148 Unknown | 432 | 1,496 | 0.05%
com.moz.by.RaceActivity$Panel @ 0x40653878 Unknown | 432 | 1,496 | 0.05%
com.moz.by.RaceActivity$Panel @ 0x40788490 Unknown | 432 | 1,496 | 0.05%
com.moz.by.RaceActivity$TutorialThread @ 0x40569580 Thread-35 | 120 | 192 | 0.01%
com.moz.by.RaceActivity$TutorialThread @ 0x40642558 Thread-37 Unknown| 120 | 192 | 0.01%
com.moz.by.RaceActivity$TutorialThread @ 0x40683108 Thread-59 Unknown| 120 | 120 | 0.00%
com.moz.by.RaceActivity$TutorialThread @ 0x406a56f0 Thread-57 | 120 | 192 | 0.01%
com.moz.by.RaceActivity$TutorialThread @ 0x40706f20 Thread-51 | 120 | 192 | 0.01%
com.moz.by.RaceActivity$TutorialThread @ 0x40707fe8 Thread-45 Unknown| 120 | 192 | 0.01%
com.moz.by.RaceActivity$TutorialThread @ 0x4077fa10 Thread-53 Unknown| 120 | 192 | 0.01%
com.moz.by.RaceActivity$TutorialThread @ 0x40789da0 Thread-43 | 120 | 192 | 0.01%
------------------------------------------------------------------------------------------------------------------
编辑:
所以看起来对 RaceActivity 的最后引用是在内部类 TutorialThread 中,它似乎在 this$0 变量中持有对该类的引用。见下文。
Type |Name |Value
-----------------------------------------------------------
ref |this$0 |com.moz.by.RaceActivity @ 0x4053b080
ref |mSurfaceHolder|null
ref |mPanel |null
boolean|mRun |false
-----------------------------------------------------------
我不确定为什么会这样,这就是我结束话题的方式。
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我认为这应该结束线程,但由于奇怪的 this$0 变量中的最终引用,它永远不会被 GC 处理。任何人都知道这个变量是什么以及我如何清除它?
最佳答案
您喜欢这个 Activity ,可能是因为您对它有一些静态引用,或者您知道如何将它传递给下一个 Activity 。
顺便问一下,当你停止线程时,你是这样做的吗?
Thread myThread = new Thread();
try {
myThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myThread = null;
你应该。
关于java - Android Activity 从未被 GC 导致内存不足异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8918922/