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

nKn*_*nKn 8 android memory-leaks hprof ddms android-bitmap

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

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

泄漏嫌疑人

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

支配树

所以基本上有一个巨大的byte[]实例保留了大量的堆,并且从未被释放.根据这个,我复制了byte[]它的值,将它转储到一个.data文件中,用Gimp打开,结果如下:

PNG

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

  • 我的所有图像文件都是<8K
  • 其中只有一些是PNG - 剩下的我能够转换为JPG,我做到了
  • 没问题,如果我添加更多图像,其大小byte[]始终与应用程序的开始大致相同(4个月前)
  • 为了调试它,我试图从和文件夹中删除任何图像文件并运行应用程序没有任何可绘制的资源,并且仍然存在drawabledrawable-xxxbyte[]
  • 我删除了几乎所有的布局,只让基本的功能,同样的结果
  • Dominator树中,根类是android.graphics.Bitmap

任何人都知道它是什么byte[]以及我是否应该做任何事情来解放它?

任何帮助赞赏!

Tan*_*ien 7

只是为了澄清一些事情:

  • 应用中的图像/绘图用于内存中的形式android.graphics.Bitmap.
  • 从Android 3.0(API级别11)开始,像素数据与关联的位图一起存储在Dalvik堆上.(管理位图内存)
  • "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).有关此内容的更多信息,请参阅支持多个屏幕.

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

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

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

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

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

- 更新 -

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

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

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

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