哪些 Android 工具和方法最适合查找内存/资源泄漏? [关闭]

Posted

技术标签:

【中文标题】哪些 Android 工具和方法最适合查找内存/资源泄漏? [关闭]【英文标题】:What Android tools and methods work best to find memory/resource leaks? [closed] 【发布时间】:2010-11-11 22:36:25 【问题描述】:

我已经开发了一个 android 应用程序,我正处于一个手机应用程序开发阶段,一切似乎都运行良好,你想宣布胜利并发布,但你知道只需要一些记忆以及那里的资源泄漏; Android 上只有 16mb 的堆空间,而且在 Android 应用中很容易泄漏。

我一直在四处寻找,到目前为止只能挖掘关于“hprof”和“traceview”的信息,但都没有得到很多好评。

您在 OS 项目中遇到或开发并愿意分享哪些工具或方法?

【问题讨论】:

我可以投票让 Р̀СТȢѸ́ФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ 将他的名字改成人类可读的名字。 如果我们从问题标题中删除“Android 工具”一词,是否可以重新打开此问题?这里找到的答案对于解决我的内存泄漏问题非常有用 好的,所以我有一个用户经常在活动之间切换,这意味着他们可能在 20 秒内切换了 15 个活动。这可能是导致内存不足错误的原因吗?我应该怎么做才能修复它?谢谢! 由于问题已关闭,因此无法提供此回复,但我建议您查看Leak Canary。只需使用您的应用程序,打开和关闭活动,然后让图书馆完成它的工作。它甚至会告诉您泄漏发生的位置。泄漏发生后,只需给泄漏分析仪一些时间来完成工作 - 通常需要大约 2 分钟或更长时间才能找到泄漏源。之后,它会在应用程序内整齐地呈现给您。无需额外工具! 【参考方案1】:

我发现开发 Android 应用程序的最常见错误之一是“java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget”错误。我在更改方向后使用大量位图的活动上经常发现此错误:活动被销毁,再次创建,布局从 XML 中“膨胀”,消耗了位图可用的 VM 内存。

前一个活动布局上的位图没有被垃圾收集器正确释放,因为它们交叉引用了它们的活动。经过多次实验,我找到了一个非常好的解决这个问题的方法。

首先,在 XML 布局的父视图上设置“id”属性:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_
     android:layout_
     android:id="@+id/RootView"
     >
     ...

然后,在 Activity 的 onDestroy() 方法上,调用 unbindDrawables() 方法,将引用传递给父 View,然后执行 System.gc()

@Override
protected void onDestroy() 
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc();



private void unbindDrawables(View view) 

    if (view.getBackground() != null) 
        view.getBackground().setCallback(null);
    

    if (view instanceof ViewGroup) 
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) 
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        

        ((ViewGroup) view).removeAllViews();
    

这个 unbindDrawables() 方法递归地探索视图树并且:

    移除所有背景可绘制对象的回调 删除每个视图组中的子项

【讨论】:

解决一个常见问题的好方法。 这不适用于 AdapterView 的子类(ListView、GridView 等)。 @Arjun 是的..它不适用于 AdapterView 子类。为此,您需要处理异常。休息它工作正常。这就是我在我的代码中使用的,它工作正常。希望这会有所帮助。 @hp.android 通过“在异常中处理这个”你有一个例子来说明它的样子吗?我问是因为我的PageAdapter 中有几页图像,我被这个错误解决了:( @Jackson 只需更改条件: if (view instanceof ViewGroup && !(view instanceof AdapterView)) 这将摆脱您为 Adapter 获得的异常【参考方案2】:

如果您只使用位图背景,@hp.android 的答案效果很好,但在我的情况下,我有一个 BaseAdapterGridView 提供一组 ImageViews。我按照建议修改了unbindDrawables() 方法,因此条件是:

if (view instanceof ViewGroup && !(view instanceof AdapterView)) 
  ...

但问题是递归方法从不处理AdapterView 的子代。为了解决这个问题,我改为执行以下操作:

if (view instanceof ViewGroup) 
  ViewGroup viewGroup = (ViewGroup) view;
  for (int i = 0; i < viewGroup.getChildCount(); i++)
    unbindDrawables(viewGroup.getChildAt(i));

  if (!(view instanceof AdapterView))
    viewGroup.removeAllViews();

这样AdapterView 的子代仍会被处理——该方法只是不会尝试删除所有子代(不受支持)。

这并不能完全解决问题,但是因为ImageViews 管理的位图不是他们的背景。因此,我添加了以下内容。这并不理想,但它有效:

if (view instanceof ImageView) 
  ImageView imageView = (ImageView) view;
  imageView.setImageBitmap(null);

总体上unbindDrawables()方法是:

private void unbindDrawables(View view) 
  if (view.getBackground() != null)
    view.getBackground().setCallback(null);

  if (view instanceof ImageView) 
    ImageView imageView = (ImageView) view;
    imageView.setImageBitmap(null);
   else if (view instanceof ViewGroup) 
    ViewGroup viewGroup = (ViewGroup) view;
    for (int i = 0; i < viewGroup.getChildCount(); i++)
    unbindDrawables(viewGroup.getChildAt(i));

    if (!(view instanceof AdapterView))
      viewGroup.removeAllViews();
  

我希望有一种更有原则的方法来释放这些资源。

【讨论】:

【参考方案3】:

关于 Android 内存管理的 Google I/O 演讲(2011 年),以及有关内存分析工具和技术的详细信息:http://www.youtube.com/watch?v=_CruQY55HOk

【讨论】:

或对应博文:android-developers.blogspot.com/2011/03/… 好的,所以我有一个用户经常在活动之间切换,这意味着他们可能在 20 秒内切换了 15 个活动。这可能是内存不足错误的原因吗?我应该怎么做才能修复它?谢谢!'【参考方案4】:

Valgrind 已移植到 Android(由 Mozilla 赞助)。请参阅 Valgrind on Android — Current Status 和 Support Running Valgrind for Android on ARM(评论 67)。

【讨论】:

这需要构建自定义 rom。【参考方案5】:

主要面向来自未来的 Google 旅行者:

不幸的是,大多数 java 工具都不适合这项任务,因为它们只分析 JVM-Heap。但是,每个 Android 应用程序也有一个本机堆,它也必须在 ~16 MB 的限制内。例如,它通常用于位图数据。因此,如果您使用大量可绘制对象,即使您的 JVM 堆在 3 MB 左右,您也很容易遇到内存不足错误。

【讨论】:

启动 Android 3.0 (honeycomb) 可绘制对象存储在堆中 @Timo 那么您将使用什么来检测本机堆中的泄漏? 测试,大量测试。问题是,由于内存共享和其他优化技术,您甚至无法真正知道您的应用程序正在使用多少内存。您可以使用常用的 shell 命令获取内存读数,但这些都是非常非常粗略的估计。【参考方案6】:

获取 Eclipse 内存分析器 (http://www.eclipse.org/mat/) 检查http://kohlerm.blogspot.com/2010/02/android-memory-usage-analysis-slides.html 和http://kohlerm.blogspot.com/search/label/memory

【讨论】:

【参考方案7】:

嗯,这些是与 Android 使用的独特格式挂钩的工具..我认为您可能不满意的是正在使用的底层测试代码框架..

您是否尝试过使用 Android Mock 框架模拟测试代码区域?

【讨论】:

不多,测试这种性质与其说是记录应用程序运行时实际发生的事情,我真正需要的是资源/内存泄漏分析工具

以上是关于哪些 Android 工具和方法最适合查找内存/资源泄漏? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

SQL注入哪些工具最有效

webpack入门

哪种算法最适合在树中查找 LCA?

Android内存泄漏查找和解决

国内都有哪些好用项目管理工具?

android性能测试工具都有哪些