有时,特别是在我的应用程序中实现新功能时,我使用DDMS + HPROF来分析内存和堆使用情况。由于应用程序似乎没有任何性能-ANR问题,并且一切顺利,最初我并不关心它 - 但现在,因为我看到它大致总是相同的大小,我想知道该死的是什么是
每次运行HPROF时,都会检查 Leak suspects 标签。总有一个android.graphics.Bitmap
实例占用了所有已用堆的大约25%。
我想进一步了解那是什么,所以我打开了 dominator tree ,看到了这个:
所以从根本上说,有一个庞大的byte[]
实例保留了大量的堆,并且永远不会被释放。根据{{3}},我复制了byte[]
的值,将其转储到.data
文件中,使用Gimp打开,结果如下:
所以基本上,它看起来像PNG图像的“alpha(0)”部分。考虑到以下事实:
byte[]
的大小始终与应用程序的开始大致相同(4个月前)drawable
和drawable-xxx
文件夹中删除任何图像文件,并运行没有任何可绘制资源的应用,以及{{1} <仍然存在byte[]
任何人都知道这是什么android.graphics.Bitmap
以及我是否应该做任何事情来解放它?
任何帮助表示赞赏!
答案 0 :(得分:7)
只是为了澄清一些事情:
android.graphics.Bitmap
。泄漏嫌疑人报告可能会有所帮助,但在这种情况下,考虑到其最大的嫌疑人只有超过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设备/模拟器上运行你的应用程序,看看是否使用了相同的内存。
作为另一个测试,您是否尝试检查准系统应用程序(删除所有可绘制的内容等)的内存使用情况?