关于android中最大堆大小和可用内存的两个问题

Posted

技术标签:

【中文标题】关于android中最大堆大小和可用内存的两个问题【英文标题】:Two questions about max heap sizes and available memory in android 【发布时间】:2011-05-20 02:19:26 【问题描述】:

我看到堆大小会根据应用程序的需要自动增加,直到手机的最大堆大小是多少。我还看到最大堆大小因设备而异。

所以我的第一个问题是,android 设备上典型的最大堆大小是多少?我已经在一部手机上测试了内存分配,它能够使用超过 40mb 的堆,而另一部手机在 20 mbs 中给出了 OutOfMemory 错误。什么是常用的最低值,什么是常用设备上的最高值?有标准还是平均?

第二个问题,也是更重要的一个问题,是如何确保您能够使用每台设备的可用资源,但又避免使用过多?我知道有诸如 onLowMemory() 之类的方法,但这些方法似乎仅适用于整个系统内存,而不仅仅是针对您的特定应用程序的堆。

有没有办法检测设备的最大堆大小并检测可用堆内存何时达到应用程序的低点?

例如,如果设备只允许 24mb 的最大堆并且应用程序接近分配限制,那么它可以检测并缩减。但是,如果设备可以轻松处理更多内容,它将能够利用可用的资源。

谢谢

【问题讨论】:

它涉及处理图像,20mb的内存很容易与图像一起使用。一次使用更少的内存和更少的进程是完全可以的,但如果设备可以处理,我希望能够让应用程序更快地处理它们。 另外,即使考虑到使用更少的内存,理想的上限是多少? 【参考方案1】:

早期设备的每个应用的上限为 16MB。后来的设备将其增加到 24MB。未来的设备可能会提供更多。

该值反映了设备上可用的物理内存和显示设备的属性(因为能够显示更多颜色的更大屏幕通常需要更大的位图)。

编辑:其他思考...

我不久前读过一篇文章,指出垃圾收集分配器本质上是对具有无限内存的机器进行建模。您可以根据需要分配多少,它会处理细节。 Android 大多以这种方式工作;你保留对你需要的东西的硬引用,对你可能不需要的东西的软/弱引用,并丢弃对你不再需要的东西的引用。 GC 将其全部整理出来。

在您的特定情况下,您将使用软引用来保留那些您不需要在内存中保存但如果有足够空间则希望保留的东西。

这开始与位图分崩离析,主要是因为一些早期的设计决策导致了“外部分配”机制。此外,软引用机制需要一些调整——初始版本倾向于保留所有内容或丢弃所有内容。

Dalvik 堆正在积极开发中(例如,参见 Android 2.3 “Gingerbread”上的注释,它引入了并发 GC),因此希望这些问题将在未来的版本中得到解决。

编辑:更新...

“外部分配”机制在 4.0(冰淇淋三明治)中消失了。位图的像素数据现在存储在 Dalvik 堆中,避免了之前的烦恼。

最近的设备(例如 Nexus 4)将堆大小限制在 96MB 或更大。

可以从ActivityManager.getMemoryClass() 获取应用程序内存限制的一般意义作为“内存类”。可以从java.lang.Runtime 函数maxMemory() 获得更具体的值。

【讨论】:

【参考方案2】:

以下是某些特定设备的“正常”(见下文)堆大小:

G1:16MB 摩托机器人:24MB Nexus One:32MB 优派 GTab:32MB Novo7 圣骑士:60MB

我说“正常”是因为某些版本的 Android(例如 CyanogenMod)允许用户手动调整堆限制。结果可以大于或小于“正常”值。

有关其他信息,请参阅此答案,包括如何以编程方式找出堆大小实际是多少,以及如何区分一方面的绝对堆大小限制和理想情况下应该尊重的堆限制其他:

Detect application heap size in Android

要检测您当前的堆利用率,您可以尝试使用 Runtime 类的 totalMemory() 方法。但是,我读过报告称,Android 操作系统的不同版本/实现可能有不同的策略,即本机内存(从中分配位图的后备内存)是否计入堆的最大值。而且,从 3.0 版本开始,本机内存直接从应用程序自己的堆中获取。

这种计算的不确定性让我认为在运行时监控应用程序的内存使用情况并不断将其与可用量进行比较是错误的。此外,如果您正在进行相关计算,并且发现内存不足,取消该计算并不总是方便或合理的,如果这样做可能会给您的用户带来不好的体验。

相反,您可以尝试在应用的功能行为上先发制人地定义某些模式或约束,以确保它处于当前设备的相关堆限制范围内(在应用初始化期间检测到)。

例如,如果您的应用使用大量单词,而这些单词必须一次全部加载到内存中,那么您可能会限制您的应用,以便对于较小的堆限制,只有较小的更常用单词列表可以被加载,而对于更大的堆限制,可以加载包含更多单词的完整列表。

还有一些 Java 编程技术允许您声明某些内存可由垃圾收集器按需回收,即使它具有现有的“软”(而不是硬)引用。如果您有想要保留在内存中的数据,但如果需要,可以从非易失性存储(即缓存)重新加载,那么您可以考虑使用软引用在您的应用程序时自动释放这些内存开始碰到堆的上限。有关 Android 中软引用的信息,请参阅此页面:

http://developer.android.com/reference/java/lang/ref/SoftReference.html

【讨论】:

以上是关于关于android中最大堆大小和可用内存的两个问题的主要内容,如果未能解决你的问题,请参考以下文章

如何设置jvm的大小?jvm的大小收到哪些因素限制,例如系统可用虚拟内存

JVM调优

JVM调优

JVM调优

JVM调优总结

JVM调优总结