Android Context Memory Leak ListView 由于 AudioManager
Posted
技术标签:
【中文标题】Android Context Memory Leak ListView 由于 AudioManager【英文标题】:Android Context Memory Leak ListView due to AudioManager 【发布时间】:2011-09-20 15:56:13 【问题描述】:我有一个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
,应用程序根本没有声音。请帮忙,这让我发疯了。显然是想弄清楚为什么会发生这种情况以及根本问题是什么?
【问题讨论】:
是的,有静态变量,只是从具有 ListView 的活动之一中删除了所有这些变量。但同样的上下文仍在泄漏。 正如我所说,AudioManager 从字面上看绝对没有出现在我的代码中,甚至出现在我正在使用的任何库中。因此我继续困惑 你有没有想过是什么原因造成的? 我面临同样的问题。我的一项活动即使在被销毁后仍留在记忆中。 MAT 显示 AudioManager 正在持有它,我没有在任何地方使用 AudioManager。对此有何想法? 我也有这个问题...有什么解决办法吗?真的很烦人......我的很多活动无缘无故地跟不上这个问题 【参考方案1】:与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 不知何故没有正确清理自己。
【讨论】:
【参考方案2】:您的代码中有几个对AudioManager
的引用不是您主动创建的。例如。每个可点击的View
可能都有一个可以播放 onClick 声音 [source]。我想这是链接。
如果您在“设置”中禁用点击声音,该代码似乎不会创建对AudioManager
的引用。你可以试试看是否还有泄漏。
泄漏的原因可能是您在 ListView(适配器?)代码中持有一些 View
对象。如果您保留它们,那么您可能有一个 View
有一个 AudioManager
reference 并保留一个 Context
参考)
【讨论】:
我认为大多数应用程序都有同样的问题。 我认为答案不应该围绕上下文展开。AudioManager
是一个单例类和一个系统类。垃圾收集器知道这一点并相应地执行适当的收集。您需要做的就是在转储内存之前执行一次 GC 调用。【参考方案3】:
我遇到了同样的问题,但在遵循以下建议后它就消失了。
Guy 先生建议不要在调试器中进行堆转储,并在获得转储之前导致一些 GC。 https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ew6lfZUH0z8
【讨论】:
【参考方案4】:在这种情况下,您可以使用应用程序上下文来避免泄漏。我不知道为什么,但是当我开始使用应用程序上下文时,问题就消失了。
【讨论】:
【参考方案5】:我在应用程序中发现的最常见原因是通过 XML 文件初始化了一些组件。当你这样做时,Activity Context
会被注入,但有时你只需要一个ApplicationContext
。对于 Android 中的 Web View,这个技术对我帮助很大。
【讨论】:
【参考方案6】:我想分享我对同一问题的经验,默认情况下我将一些 Activity 保留在堆栈中并且没有完成它们。
对于这些活动,我得到的结果与上面 hprof 报告中提到的相同。
一旦我完成不再使用的活动,上面的引用就没有了。在不再需要的时候完成你的活动,然后这个问题就会得到解决。
【讨论】:
【参考方案7】:这是一个复制问题的非常基本的活动(至少在 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。这当然不方便。
【讨论】:
【参考方案8】:如果您的应用程序因内存泄漏而崩溃,那么您可以使用 try - catch(java.lang.outofmemory) 来避免这种崩溃。事实上,GC 是由 JVM 自己调用的,因此程序员对此没有控制权。您可以将应用程序安装在 SD 卡中,在这种情况下将使用 SD 卡内存。不会发生内存泄漏。
只要去你的清单文件,必须有版本号。版本名称,还必须有“安装位置”,改成“preferExternal”。
【讨论】:
我认为这不能回答我的问题。 @santanu, 您可以在 SD 卡中安装您的应用程序,在这种情况下将使用 SD 卡内存。不会发生内存泄漏。什么鬼? @haibison 内存泄漏是different。这是关于 RAM 被不必要地使用,与 SD 卡无关。 @zapl,谢谢 :-) 我明白这一点。我只是对他的信息感到困惑。 @haibison 哎呀,这是一个报价。我已经想知道你们都对 sd 卡有什么了解以上是关于Android Context Memory Leak ListView 由于 AudioManager的主要内容,如果未能解决你的问题,请参考以下文章
用verilog写的ROM用quartusII综合后为啥没综合到memory bit里而是综合到了LE里面要怎样才能弄到memory
[CodeForces - 712D]Memory and Scores (DP 或者 生成函数)
UnityVR一体机报错:GL_OUT_OF_MEMORY,[EGL] Unable to acquire context
Ubuntu elasticsearch max virtual memory areas vm.max_map_count [65530] is too low, increase to at le