大堆大小的原因定位和补救
Posted
技术标签:
【中文标题】大堆大小的原因定位和补救【英文标题】:Locating and remedying cause of large heap size 【发布时间】:2012-03-28 01:10:39 【问题描述】:我正在尝试找出为什么我的应用使用了这么多内存。我经常看到它使用 15 到 18MB,这大大高于我的预期。我通过 DDMS 查看了堆大小并看到了这个:
这看起来有点可疑,因为我的应用根本不处理大图像。事实上,我的应用程序中可绘制的总和约为 250KB。所以我创建了一个堆转储并使用 MAT 来定位所有这些内存的去向。 byte[] 数组是迄今为止最大的消费者,所以我深入研究并注意到以下内容:
我完全不知道为什么 sPreloadedDrawables 会造成如此高的保留堆大小。我也不知道如何确定根本原因,或者如何“修复”它。
我应该从这里去哪里?我的应用程序主要通过根本不处理图像数据的服务在后台运行。我确实有用户可以选择使用的活动,但同样,他们使用小型可绘制对象,不能解释如此大的堆大小。我还检查了任何令人讨厌的 Activity 泄漏等情况,但没有找到。
编辑:我注意到在模拟器中运行时堆大小要小得多。这很令人困惑。 :/
【问题讨论】:
您的手机运行的是哪个 android 版本?我注意到 ICS 会预加载图像可绘制对象,我想尝试获得更流畅的 UI 体验并利用增加的 VM 内存限制。因此,如果您的手机在 ICS 上,而您的模拟器在 2.X 上,这将解释差异。我个人还没有测试过运行 4.X 的模拟器来检查膨胀的内存是否也存在(我想我以后要做点什么)。它肯定在我运行 4.0.3 的手机上。 我的手机运行的是 Android 4.0.3,模拟器也是。 您在模拟器和设备上使用的屏幕密度/尺寸是多少? 当您的应用在前台运行时,为什么要担心堆大小?除非您的应用作为服务运行 【参考方案1】:系统将预加载默认系统资源,这与您的应用资源无关,例如用于复选框和单选按钮的标准 Drawable。 10.5MB 看起来确实很大,但是有很多默认的系统资源,并且图像一旦存储在内存中就更大了。预加载不是新的,但预加载的大小在 ICS 中可能更大。显示密度可能在这方面发挥了作用,只是在 ICS 中添加了更多预加载的系统 Drawable。
目前没有办法减少sPreloadedDrawables
持有的内存
很遗憾,在为不使用大部分系统 Drawable 的应用(尤其是游戏)生成应用进程后,无法清除此问题。在这种情况下,尽管预加载资源的大尺寸似乎是 ICS 特定版本(或手机端口)的错误。否则通常会占用少量内存,因此我怀疑是否有必要使用这种机制来减少预加载内存的使用。
如果由于此缓存而导致内存不足,那么我可能会向 Google 提交错误报告。
如果您对更多内部细节感兴趣,可以在此处跟踪资源预加载过程。 ZygoteInit.preloadResources
【讨论】:
是的。不会有关闭此功能的功能 - 它是在 zygote 进程中完成的,该进程创建一次,并且所有应用程序进程都从该进程生成。它加载的资源因此在所有进程之间共享。 谢谢西斯特恩斯。我的主要问题是我让用户看到了这种内存使用情况并报告了它。它影响了我的星级。我的手机使用与 iPhone 4 相同的显示屏,因此它的密度非常高(类似于 320dpi)。根据 Android 的报告,在库存 ICS 上,它会使用超过 20MB 的空间。有趣的是,在更新到更高版本后,它已降至约 7MB。所以我想知道,这也可能是 ICS 端口不良的产物吗? 听起来这是一个错误,导致在预加载期间加载的项目比预期的多(或更大)。 @hackbod 我还没有完全深入研究 zygote 以查看它被用作生成器(非常酷),所以我明白为什么总是需要进行预加载。可以添加支持以在分叉后清除预加载资源。但鉴于大尺寸似乎是一个错误,而且它通常很小,我怀疑它是否有必要。 @hackbod 在 Android 4.1 上,在我们的应用程序的堆转储中,sPreloadedDrawables 仍然占用大约 5MB 的保留内存。这算不算正常金额?我还应该补充一点,由于来自 sPreloadedDrawables 的强引用,内存中的 2 个资源的大小为 1MB每个。 Android 中哪个默认可绘制对象会占用这种空间? 它确实是特定于设备的。在新的高分辨率屏幕和添加自定义默认可绘制对象的 OEM 之间,更大的图像可能会潜入。以上是关于大堆大小的原因定位和补救的主要内容,如果未能解决你的问题,请参考以下文章