2011-06-22 19 views
21

我有一个ListView,我期望它在活动结束时从内存中清除。但是,它似乎正在泄漏。当我检查了内存转储,并得到pathToGCListView我得到以下,由于AudioManager引起的Android上下文内存泄漏列表视图

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,根本没有声音来自应用程序。请帮忙,这让我疯狂。显然试图找出为什么会发生这种情况,根本问题是什么?

+0

你使用任何静力学? – mibollma

+0

嗯,是有静态变量,只是从一个具有ListView的活动中删除所有这些变量。但是同样的情况仍然在泄漏。 – Leo

+0

它与ListView以及与AudioManager无关。你在用AudioManager做什么? – cyngus

回答

-4

如果您的应用程序崩溃了内存泄漏,那么您可以使用try-catch(java.lang.outofmemory)来避免此崩溃。事实是GC由JVM本身调用,因此程序员无法控制这一点。您可以将应用程序安装在SD卡中,在这种情况下,将使用SD卡存储器。内存泄漏不会发生。

只要进入你的清单文件,必须有版本号。版本名称,还必须有“安装位置”,使其成为“preferExternal”。

+0

我不认为这回答了我的问题。 – Sameer

+0

@santanu,_您可以将您的应用程序安装在SD卡中,在这种情况下,将使用SD卡存储器。内存泄漏将不会发生。我勒个去? – 2012-03-17 23:16:40

+1

@haibison内存泄漏是[不同](http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html)。这是关于RAM被不必要地使用,并且与SD卡无关。 – zapl

5

在您的代码中有几处引用AudioManager,您不会主动创建。例如。每个可点击的View可能有一个可以播放onClick声音[source]。我想这是链接。

如果您在设置中停用了点击声音,代码看起来像不会创建对AudioManager的引用。你可以尝试,并检查是否仍然有泄漏。

您泄漏的原因可能是您在ListView(Adapter?)代码中持有一些View对象。如果你让他们身边,那么你可能有一个View有一个AudioManagerreference,并且保持一个Context参考)

+0

因为我认为大多数应用程序在那里我有同样的问题。 –

+2

我不认为答案应该围绕上下文进行。 'AudioManager'是一个单例类和一个系统类。垃圾收集器知道这一点,并相应地执行适当的收集。您只需在转储内存之前进行GC调用即可。 – redDragonzz

0

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

0

我想分享我的经验,关于同一个问题,我保留了一些活动在默认情况下堆栈,并没有完成他们。

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

一旦我完成不再使用活动,上述参考没有来。只需完成不再需要的活动,就可以解决此问题。

1

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

7

完全不相关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的错误实例if你从应用程序上下文中获得它)。

最后,您可能想知道为什么成员变量(AudioManager)阻止垃圾收集类(Activity)。从内存分析器中可以看出,AudioManager属于本地堆栈。所以AudioManager不能正常清理本身。

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]; 
    } 
} 

正如你可以看到有没有与活动相关意见或Layots,也是我将“静音”系统声音设置中的配置文件,并关闭“振动触摸”。

现在,几(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设备监控垃圾确实从内存中删除的活动,也就是在这个过程

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

的logcat的状态我也试图构建发布版本的apk和它的行为相同。所以它不是调试器持有的参考。

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