Android上下文内存泄漏ListView由于AudioManager

我有一个ListView ,我期望它在活动结束时从内存中清除。 但是,它似乎正在泄漏。 当我检查内存转储,并获得ListViewpathToGC我得到以下,

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

Solutions Collecting From Web of "Android上下文内存泄漏ListView由于AudioManager"

与OP的泄漏无关,但是由于AudioManager导致泄漏的人员来到这里:

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

如果video被加载,VideoView从不发布AudioManager。

正如链接中提到的那样,使用ApplicationContext手动创buildVideoView。

编辑:这个解决方法将工作,直到…如果video解码器说video有编码问题。 VideoView尝试使用应用程序上下文popupAlertDialog。 比发生崩溃。

我唯一能想到的工作就是继续使用活动上下文创buildvideo视图,在activity.onDestroy中,使用reflection将AudioManager的mContext设置为应用程序上下文。

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

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

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

代码看起来像不会创build对AudioManager引用,如果您禁用设置中的点击声音。 你可以尝试一下,检查是否还有泄漏。

你泄露的原因可能是你在ListView(Adapter?)代码中持有一些View对象。 如果你保持它们,那么你可能有一个View有一个AudioManager 引用,并保持一个Context引用)

我有这个相同的问题,但按照下面的build议后,它消失了。

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

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

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

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

对于这些活动,我和hprof报告中提到的一样。

一旦我完成不再使用的活动,上面的引用没有来。 只要在不再需要的时候完成你的活动,那么这个问题将得到解决。

这是一个很复杂的问题(至less在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]; } } 

如您所见,没有与活动关联的视图或图层,我还在系统“声音设置”中设置了“无声”configuration文件,并closures了“振动触摸”。

现在,几(5-7取决于你的堆大小)重新启动此活动生成java.lang.OutOfMemoryError试图创build新的数组。

 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) 

我也尝试构buildapk的发行版,它的行为相同。 所以它不是debugging器持有的参考。

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

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

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