查找并修复Android中的内存泄露—OutOfMemoryError(android 内存泄露检测)

网友投稿 631 2022-09-24

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

查找并修复Android中的内存泄露—OutOfMemoryError(android 内存泄露检测)

java.lang.OutOfMemoryError: Failed to allocate a 4308492 byte allocation with 467872 free bytes and 456KB until OOMat dalvik.system.VMRuntime.newNonMovableArray(Native Method)at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:988)at android.content.res.Resources.loadDrawableForCookie(Resources.java:2580)at android.content.res.Resources.loadDrawable(Resources.java:2487)at android.content.res.Resources.getDrawable(Resources.java:814)at android.content.res.Resources.getDrawable(Resources.java:767)at com.nostra13.universalimageloader.core.DisplayImageOptions.getImageOnLoading(DisplayImageOptions.java:134)

啥?这是什么意思?是说我的位图(bitmap)太大了吗?

不幸的是,这种堆栈跟踪往往带点迷惑性。通常,如果遇到 OutOfMemoryError 错误,十有八九是因为内存泄露。当笔者第一次遇到这种堆栈跟踪时,也感到迷惑不解,想着是不是位图太大了……实际上,我那会儿真是大错特错。

什么是内存泄露?

内存泄露是指程序释放废弃内存失败,导致性能受损或出现中断。

Android 程序中的内存泄露是如何产生的?

每个 app 都有一个全局的应用上下文对象( getApplicationContext())。每个 Activity (活动)都是 Context 的子类,存储着与当前活动相关的信息。通常,内存泄露都与已泄露的活动(leaked activtiy)相关。

通常,一般的开发者会把上下文对象(context object)传给需要的线程。创建一些静态的 TextViews 以存储指向活动的引用。但是,你懂的,这样可行吗?

在此情况下,如果使用内存监视器就会发现,app 的内存使用率不断增加,正如下面的 Android 内存监控器所示:

如你所见,在第一张图中,app 永远都无法回收一部分已经使用的内存。在 OutOfMemoryError 错误出现之前,它一度使用了300MB的内存。而第二张图则显示,app 能顺利进行垃圾回收,重得一部分内存,从而保持相当稳定的内存使用量。

如何避免内存泄露?

避免在 activity 或 fragment 之外传递 Context 对象。永远永远不要创建静态的 Context 或 View 对象,或者将二者存储于静态变量中。这是内存泄露的首要标志。

private static TextView textView; //DO NOT DO THISprivate static Context context; //DO NOT DO THIS

如何修复内存泄露问题?

修复内存泄露问题需要许多实践,不断尝试、试错,才能取得成功。通常,内存泄露并不容易定位。值得庆幸的是,有许多现成的工具可以帮你找出潜在的泄露问题。

./hprof-conv path/file.hprof exitPath/heap-converted.hprof

现在,保存着引用的线程就会显示出来。之后,你可以追根溯源,找到存储该 activity 引用的具体实例。

因此,对这个此前登记的显示监听器(display listener)调用注销方法,就能解决此内存泄露问题。

DisplayManager displayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);displayManager.unregisterDisplayListener(listener);

上一篇:为什么选用 React 创建混合型移动应用?(为什么选用哺乳动物成熟的红细胞)
下一篇:如何选择一款好的 APM 工具?(如何选择一款好的冲牙器)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~