21

我有一个ListView,我希望它在活动完成时从内存中清除。但是,它似乎正在泄漏。当我检查内存转储并获得pathToGC以下ListView内容时,

Class Name                                                          | Shallow Heap | Retained Heap 
android.widget.ExpandableListView @ 0x4063e560                      |          768 |        39,904 
|- list, mList com.hitpost.TeamChooser @ 0x405f92e8                 |          176 |         1,648 
|  '- mOuterContext android.app.ContextImpl @ 0x40657368            |          160 |           304 
|     '- mContext android.media.AudioManager @ 0x40662600           |           40 |           168 
|        '- this$0 android.media.AudioManager$1 @ 0x406626b0 Unknown|           24 |            24 

我在很多我的ListView's. 诀窍是,我根本没有AudioManager在我的应用程序中使用任何地方,根本没有来自应用程序的声音。请帮忙,这让我发疯了。显然试图弄清楚为什么会发生这种情况以及根本问题可能是什么?

4

8 回答 8

8

与OP的泄漏无关,但对于因AudioManager导致泄漏而来到这里的人:

如果您因为使用 VideoView 而看到此泄漏,可能是因为此错误:https ://code.google.com/p/android/issues/detail?id=152173

如果视频正在加载,VideoView 永远不会释放 AudioManager。

如链接中所述,修复方法是使用 ApplicationContext 手动创建 VideoView。

编辑:这个解决方法将起作用,直到......如果视频解码器说视频有编码问题。VideoView 尝试使用应用程序上下文弹出一个 AlertDialog。比发生崩溃。

我能想到的唯一解决方法是继续使用活动上下文创建视频视图,并在 activity.onDestroy 中,使用反射将 AudioManager 的 mContext 设置为应用程序上下文。

注意:必须使用 activity.getSystemService(Context.AUDIO_SERVICE) 而不是 activity.getApplicationContext.getSystemService(Context.AUDIO_SERVICE) 来获取 AudioManager,因为 AudioManager 是 Context 的成员变量(如果从那里获取 AudioManager 实例,则会得到错误的实例)应用程序上下文)。

最后,您可能想知道为什么成员变量 (AudioManager) 会阻止类 (Activity) 被垃圾回收。从内存分析器中,它显示 AudioManager 归本机堆栈所有。所以 AudioManager 不知何故没有正确地清理自己。

于 2015-04-23T22:49:02.557 回答
5

您的代码中有几个AudioManager您没有主动创建的引用。例如,每个可点击View可能有一个播放 onClick 声音 [来源]。我想那是链接。

AudioManager如果您在设置中禁用点击声音,该代码看起来不会创建引用。你可以试试看是否还有漏气。

泄漏的原因可能是您在 ListView(适配器?)代码中持有某些View对象。如果你把它们放在身边,那么你可能会有一个ViewAudioManager 参考并且保持Context参考的)

于 2012-03-18T11:21:36.340 回答
4

我遇到了同样的问题,但在遵循以下建议后它就消失了。

Guy 先生建议不要在调试器中进行堆转储并在获得转储之前导致一些 GC。 https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ew6lfZUH0z8

于 2012-12-21T19:21:52.763 回答
1

在这种情况下,您可以使用应用程序上下文来避免泄漏。我不知道为什么,但是当我开始使用应用程序上下文时,问题就消失了。

于 2014-05-10T16:49:18.907 回答
0

我在应用程序中发现的最常见原因是通过 XML 文件初始化了一些组件。当你这样做时,Activity Context会被注入,但有时你只需要一个ApplicationContext. 关于Android中的Web View,这个技术对我帮助很大。

于 2013-11-15T04:23:29.257 回答
0

我想分享我对同一问题的经验,默认情况下我将一些 Activity 保留在堆栈中,而不是完成它们。

对于这些活动,我得到的结果与 hprof 报告中提到的相同。

一旦我完成不再使用的活动,上面的引用没有来。只需在不再需要时完成您的活动,即可解决此问题。

于 2014-01-21T04:42:55.767 回答
0

这是复制问题的非常基本的活动(至少在 Android 4.0.3 上)

public class MainActivity extends Activity {

    int image[];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main);
        image = new int[1000 * 1500 * 4];
    }
}

如您所见,没有与活动相关的视图或布局,我还在系统声音设置中设置了“静音”配置文件并关闭了“触摸时振动”。

现在,在几次(5-7 次,取决于您的 heapSize)重新启动后,此活动会在尝试创建新数组时生成 java.lang.OutOfMemoryError。

07-27 19:54:10.160  22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 25ms
07-27 19:54:10.190  22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed 23449K, 43% free 32591K/56391K, paused 30ms
07-27 19:54:10.260  22542-22543/? D/dalvikvm﹕ GC_CONCURRENT freed 0K, 1% free 56029K/56391K, paused 3ms+3ms
07-27 19:54:11.850  22542-22542/? D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 1% free 56040K/56391K, paused 20ms
07-27 19:54:11.880  22542-22542/? D/dalvikvm﹕ GC_BEFORE_OOM freed <1K, 1% free 56040K/56391K, paused 29ms
... Out of memory on a 24000016-byte allocation.

转储 .hprof 我还看到了 2 个活动,其中一个由 AudioManager 举行。

调用“更新堆”然后在 Android 设备监视器中收集垃圾确实会从内存中删除活动,这就是 logcat 在此过程中的状态

07-27 19:44:23.150        85-85/? I/DEBUG﹕ #06  pc 000382cc  /system/lib/libdvm.so (dvmCollectGarbageInternal(GcSpec const*)+1204)

我还尝试构建 apk 的发布版本,它的行为相同。所以它不是持有引用的调试器。

在我看来,这似乎是 Android 中的一个错误。解决方法是在活动的 OnStop() 或 onFinish() 中显式调用 image = null。这当然不方便。

于 2015-07-27T12:22:03.577 回答
-4

如果您的应用程序因内存泄漏而崩溃,那么您可以使用 try - catch(java.lang.outofmemory) 来避免这种崩溃。事实上,GC 是由 JVM 自己调用的,所以程序员对此没有控制权。您可以将应用程序安装在 SD 卡中,在这种情况下将使用 SD 卡内存。不会发生内存泄漏。

只需转到您的清单文件,必须有版本号。版本名称,还必须有“安装位置”,设为“首选外部”。

于 2012-03-13T06:45:38.740 回答