HPROF之后我的应用程序中的巨大字节[]

时间:2014-01-22 18:40:14

标签: android memory-leaks ddms hprof android-bitmap

有时,特别是在我的应用程序中实现新功能时,我使用DDMS + HPROF来分析内存和堆使用情况。由于应用程序似乎没有任何性能-ANR问题,并且一切顺利,最初我并不关心它 - 但现在,因为我看到它大致总是相同的大小,我想知道该死的是什么是

每次运行HPROF时,都会检查 Leak suspects 标签。总有一个android.graphics.Bitmap实例占用了所有已用堆的大约25%。

Leak suspects

我想进一步了解那是什么,所以我打开了 dominator tree ,看到了这个:

Dominator tree

所以从根本上说,有一个庞大的byte[]实例保留了大量的堆,并且永远不会被释放。根据{{​​3}},我复制了byte[]的值,将其转储到.data文件中,使用Gimp打开,结果如下:

PNG

所以基本上,它看起来像PNG图像的“alpha(0)”部分。考虑到以下事实:

  • 我的所有图像文件都是<8K大小
  • 其中一些是PNG - 剩下的我能够转换为JPG,我做了
  • 无论如何我添加更多图片,byte[]的大小始终与应用程序的开始大致相同(4个月前)
  • 要对其进行调试,我尝试从drawabledrawable-xxx文件夹中删除任何图像文件,并运行没有任何可绘制资源的应用,以及{{1} <仍然存在
  • 我删除了几乎所有的布局,只使用了基本的功能,结果相同
  • Dominator树中,根类为byte[]

任何人都知道这是什么android.graphics.Bitmap以及我是否应该做任何事情来解放它?

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:7)

只是为了澄清一些事情:

  • 您应用中的图片/绘图在内存中以android.graphics.Bitmap
  • 的形式使用
  • 从Android 3.0(API级别11)开始,像素数据与关联的位图一起存储在Dalvik堆上。 (Managing Bitmap Memory
  • “huge byte []”可能是一种夸大其辞,因为它的堆空间超过1MB。

泄漏嫌疑人报告可能会有所帮助,但在这种情况下,考虑到其最大的嫌疑人只有超过1MB的内存,它并没有告诉你多少。现代设备提供64MB +堆。

让我们对这个位图的内存要求进行数学计算。该位图在堆上占用1,127,584个字节。如果我们假设使用ARGB_8888配置此位图,则每个像素使用4个字节,这意味着您的图像包含281,896个像素(或大约530x530)。这听起来不合理吗?

另外,考虑一下Android在不同的“存储桶”中进行缩放的方式:mdpi,hdpi,xhdpi等。假设您在 mdpi 存储桶中有200x200的图像,并且您正在打开 xhdpi 设备上的应用。此图像将缩放为两倍大,并具有400x400的设备分辨率。因此,虽然200x200图像可能不会占用太多堆空间(200 x 200 x 4 = 160 kb ),但400x400图像将需要相对较大量(4x)的堆空间(400 x 400 x 4) = 640 kb )。有关详细信息,请参阅 Supporting Multiple Screens

一个很好的工具,用于快速计算与图像存储桶的差异:Android DPI Calculator

你说你删除了一些可绘制的东西,但还剩下什么?您是否考虑过可能来自外部图书馆的绘图?

回答你的最后一个问题:任何人都知道这个字节是什么[]以及我是否应该做任何事情来解放它?

我会说:你的堆上的这么少的内存是没有什么可担心的。如果它困扰你,请密切关注它并确保它不会超出实际可行的范围。如果您仍然怀疑内存泄漏,请在屏幕之间导航并观察堆是否继续增长。假设您没有缓存位图,在两个屏幕之间来回导航时,堆应该保持一致/可预测的大小

作为旁注,DDMS使得即时监控堆大小变得非常容易。在您准备好潜入之前不需要HPROF转储。请查看 Using DDMS 。请特别注意“原因GC”按钮,因为需要触发更新初始堆大小。

- 更新 -

为了进一步回答这个问题,我得到的一个不受支持的怀疑是应用程序的某些资产(系统资产/纹理?)被加载到应用程序的内存空间中。请看这里的幻灯片64:What's new in Android 4.4

  

Android 4.4现在生成一个包含所有框架资产的纹理,由所有进程共享。这样可以节省每个进程的内存,但它也有助于批处理和合并绘图操作以自动优化应用程序。

这似乎意味着内存用于运行4.4之前版本的每个应用程序中的系统位图/绘图。如果是这种情况,我会质疑这个1MB是否是那个空间。我想知道你是否可以在4.4设备/模拟器上运行你的应用程序,看看是否使用了相同的内存。

作为另一个测试,您是否尝试检查准系统应用程序(删除所有可绘制的内容等)的内存使用情况?