我看到堆大小会随着应用的需要自动增加,直到手机的最大堆大小为止。我还看到最大堆大小因设备而异。
所以我的第一个问题是,Android设备上的典型Max Heap大小是多少?我已经在一部手机上测试了内存分配,该手机能够使用超过40mb的堆,而另一部手机在20的mbs中发出OutOfMemory错误。常用设备中最低的是什么,普通设备上最高的是什么?有标准还是平均?
第二个问题,更重要的一个问题,是如何确保您能够使用每台设备可用的资源但避免使用太多?我知道有一些方法,比如onLowMemory(),但这些方法似乎只适用于整个系统内存,而不仅仅是特定应用程序的堆。
有没有办法检测设备的最大堆大小,还检测可用堆内存何时达到应用程序的低点?
例如,如果设备仅允许24mb的最大堆并且应用程序在分配中接近该限制,则它可以检测并缩小。但是,如果设备可以舒适地处理更多,它将能够利用可用的东西。
由于
答案 0 :(得分:8)
早期设备的每个应用上限为16MB。后来的设备增加到24MB。未来的设备可能会更多可用。
该值反映了设备上可用的物理内存和显示设备的属性(因为能够显示更多颜色的更大屏幕通常需要更大的位图)。
编辑:其他沉思......
我不久前读过一篇文章,指出垃圾收集分配器本质上是对具有无限内存的机器进行建模。您可以根据需要进行分配,并且会处理细节。 Android主要以这种方式工作;你会坚持引用你需要的东西,对你可能没有的东西进行软/弱引用,并放弃对你再也不需要的东西的引用。 GC对此进行了整理。
在您的特定情况下,您将使用软引用来保留您不需要的内容,但如果有足够的空间,则希望保留。
这开始与位图分离,很大程度上是因为一些早期的设计决策导致了“外部分配”机制。此外,软参考机制需要一些调整 - 初始版本倾向于保留所有内容或丢弃所有内容。
Dalvik堆正在积极开发中(参见例如Android 2.3“Gingerbread”上的注释,它引入了并发GC),所以希望这些问题将在未来版本中得到解决。
修改:更新...
“外部分配”机制在4.0(冰淇淋三明治)中消失了。 Bitmaps的像素数据现在存储在Dalvik堆上,避免了早先的烦恼。
最近的设备(例如Nexus 4)将堆大小限制在96MB或更高。
应用程序的内存限制的一般意义可以从ActivityManager.getMemoryClass()
获得“内存类”。可以从java.lang.Runtime
函数maxMemory()
获得更具体的值。
答案 1 :(得分:5)
以下是某些特定设备的“正常”(见下文)堆大小:
我说“正常”,因为某些版本的Android(例如,CyanogenMod)将允许用户手动调整堆限制。结果可能大于或小于“正常”值。
有关其他信息,请参阅此答案,包括如何以编程方式查明堆大小实际上是什么,以及如何区分绝对堆大小限制和理想情况下应该遵循的堆限制。其他:
Detect application heap size in Android
要检测当前堆利用率是多少,可以尝试使用Runtime类的totalMemory()方法。但是,我已经阅读过报告,Android OS的不同版本/实现可能有不同的策略,关于本机内存(从中分配位图的后备内存)是否计入堆的最大值。而且,从版本3.0开始,本机内存直接从应用程序自己的堆中获取。
这种计算的不确定性使我认为在运行时监控应用程序的内存使用情况是错误的,不断将其与可用数量进行比较。此外,如果您正处于涉及计算的中间,并且发现您的内存不足,则取消该计算并不总是方便或合理,如果您这样做,可能会给您的用户带来糟糕的体验。
相反,您可以尝试在应用程序的功能行为上预先定义某些模式或约束,以确保它在任何当前设备的相关堆限制下(在应用程序初始化期间检测到)。
例如,如果您的应用程序使用必须一次性加载到内存中的大量单词列表,那么您可以约束您的应用程序,以便对于较小的堆限制,只有较小的更常用单词列表可以加载时,对于较大的堆限制,可以加载包含更多单词的完整列表。
还有一些Java编程技术允许您根据需要声明某些内存可由垃圾收集器回收,即使它已经存在“软”(而不是硬)引用。如果您有想要保留在内存中的数据,但是如果需要可以从非易失性存储中重新加载(即缓存),那么您可以考虑使用软引用让您的应用程序自动释放此类内存开始碰到堆的上限。有关Android中软引用的信息,请参阅此页:
http://developer.android.com/reference/java/lang/ref/SoftReference.html