一个应用程序可以使用的最大内存量是多少?

我很好奇这个问题,关于 Android 操作系统的内存管理,所以我希望一个相当详细的答案,这个主题。

我想知道的是:

  • 什么是 最大内存容量最大内存容量(在 兆字节/as 占总 RAM 的百分比 ) ,Android 应用程序(不是系统应用程序)可以使用?
  • Android 版本Android 版本有什么不同吗?
  • 设备的 制造商有什么不同吗?

最重要的是:

  • 当系统决定一个应用程序在运行时可以使用多少内存时(假设每个应用程序的最大内存不是一个静态数字) ,什么 被认为是/它取决于什么

迄今为止(截至2013年)我听到的情况是:

  • 早期的 Android 设备每个应用程序的上限是16MB
  • 后来这个上限增加到24 MB 或32 MB

让我非常好奇的是:

这两个限制都非常低。

我刚刚下载了 Android 任务管理器来检查我的设备内存。我注意到有些应用程序使用大约40-50MB 的 RAM,这显然比上面提到的32MB 的最大 RAM 使用量要多。那么,Android 如何决定一个应用程序可以使用多少内存呢?应用程序怎么可能超过这个限制?

此外,我注意到我的一些应用程序崩溃了(被系统杀死了?)当使用大约30-40兆字节时,使用 OutOfMemory 异常。另一方面,我有应用程序在我的手机上运行一段时间后使用 100MB 以上(可能是由于内存泄漏) ,不会崩溃或死亡。 因此,当决定可以节省多少内存时,显然这也取决于应用程序本身是如何做到的呢? (我使用一个768MB 内存的 HTC One S 进行测试)

免责声明: 我不属于 Android 任务管理器应用程序在任何方式。

91055 次浏览

Android 应用程序(不是系统应用程序)可以使用的最大内存量(以兆字节为单位,占内存总量的百分比)是多少?

ABC1上的 getMemoryClass()将为您的代码所运行的设备提供值。

Android 版本之间有什么区别吗?

是的,多年来操作系统的需求不断增加,设备必须进行相应的调整。

关于设备的制造商是否有分歧?

是的,只要制造商生产设备,而且尺寸因设备而异。

在决定一个应用程序可以使用多少内存时,哪些“侧面因素”被考虑在内?

我不知道“副作用”是什么意思。

早期的设备每个应用程序的容量上限为16MB; 后来的设备增加到24MB 或32MB

差不多吧。屏幕分辨率是一个重要的决定因素,因为更大的分辨率意味着更大的位图,所以平板电脑和高分辨率手机将倾向于具有更高的价值。例如,您将看到具有48MB 堆的设备,如果有比这更高的值,我不会感到惊讶。

应用程序怎么可能超过这个限制?

您假设该应用程序的作者知道自己在做什么。考虑到 应用程序的内存使用对于一个核心的 Android 工程师来说是很难确定的,我不会认为这个应用程序一定会提供特别准确的结果。

也就是说,本机代码(NDK)不受堆限制。而且,自 Android 3.0以来,应用程序可以请求一个“大堆”,通常在数百 MB 的范围内,但这被认为是大多数应用程序的糟糕形式。

此外,我注意到我的一些应用程序在使用大约30-40兆字节时会因为 OutOfMemory 异常而崩溃。

请记住,Android 垃圾收集器不是一个压缩的垃圾收集器。CouldNotFindSufficientlyLargeBlockOfMemoryException确实应该是个例外,但它可能被认为过于冗长。OutOfMemoryException意味着你的 无法分配请求的块,并不意味着你已经完全耗尽了你的堆。

每个应用程序的内存限制取决于屏幕大小和 Android 版本: https://drive.google.com/file/d/0B7Vx1OvzrLa3Y0R0X1BZbUpicGc/view?usp=sharing

来源: Android 兼容性下载 http://source.android.com/compatibility/downloads.html; 兼容定义文档(CDD) ,节虚拟机兼容性或运行时兼容性

现在是2018年底,所以情况有所改变。

首先: 运行你的应用程序,在 Android Studio 中打开 Android Profiler 选项卡。 您将看到它消耗了多少内存,您会感到惊讶,但它可以分配很多内存。

还有官方文档中的 这是一篇很棒的文章,详细说明了如何使用内存分析器,它可以让你深入了解内存管理。

但在大多数情况下,普通的 Android Profiler 就足够了。

enter image description here

通常情况下,一个应用程序开始与50Mb 的内存分配,但立即跳跃到90Mb,当你开始加载一些照片在内存中。当你使用预装照片的 ViewPager 打开 Activity (每个3.5 Mb)时,你可以在几秒钟内轻松获得190Mb。

但这并不意味着您在内存管理方面有问题。

我能给出的最好的建议是遵循指导方针和最佳实践,使用顶级图书馆的图像加载(滑动,毕加索) ,你会没事的。


但是,如果您需要定制某些内存,并且您确实需要知道您可以手动分配多少内存,那么您可以获得总的空闲内存,并计算预先确定的部分(以% 为单位)。 在我的例子中,我需要将已解密的照片缓存在内存中,这样就不需要在用户每次浏览列表时对它们进行解密。

为此,您可以使用随时可用的 LruCache 类。这是一个缓存类,它自动跟踪你的对象分配了多少内存(或数量) ,并删除最老的内存,以保持最近的使用历史。 下面是一个关于如何使用它的很棒的教程。

在我的例子中,我创建了两个缓存实例: 用于大拇指和附件。 使他们静态的单一访问,使他们可以在整个应用程序的全球范围内。

缓存类:

public class BitmapLruCache extends LruCache<Uri, byte[]> {


private static final float CACHE_PART_FOR_THUMBS_PRC = 0.01f; // 1% (Nexus 5X - 5Mb)
private static final float CACHE_PART_FOR_ATTACHMENTS_PRC = 0.03f;// 3% (Nexus 5X - 16Mb)
private static BitmapLruCache thumbCacheInstance;
private static BitmapLruCache attachmentCacheInstance;


public static synchronized BitmapLruCache getDecryptedThumbCacheInstance() {
if (thumbCacheInstance == null) {


int cacheSize = getCacheSize(CACHE_PART_FOR_THUMBS_PRC);
//L.log("creating BitmapLruCache for Thumb with size: " + cacheSize + " bytes");
thumbCacheInstance = new BitmapLruCache(cacheSize);
return thumbCacheInstance;
} else {
return thumbCacheInstance;
}
}


public static synchronized BitmapLruCache getDecryptedAttachmentCacheInstance() {
if (attachmentCacheInstance == null) {


int cacheSize = getCacheSize(CACHE_PART_FOR_ATTACHMENTS_PRC);
//            L.log("creating BitmapLruCache for Attachment with size: " + cacheSize + " bytes");
attachmentCacheInstance = new BitmapLruCache(cacheSize);
return attachmentCacheInstance;
} else {
return attachmentCacheInstance;
}
}


private BitmapLruCache(int maxSize) {
super(maxSize);
}


public void addBitmap(Uri uri, byte[] bitmapBytes) {
if (get(uri) == null && bitmapBytes != null)
put(uri, bitmapBytes);
}


public byte[] getBitmap(Uri uri) {
return get(uri);
}




@Override
protected int sizeOf(Uri uri, byte[] bitmapBytes) {
// The cache size will be measured in bytes rather than number of items.
return bitmapBytes.length;
}
}

这就是我如何计算可用的免费内存,以及我能从中获得多少:

private static int getCacheSize(float partOfTotalFreeMemoryToUseAsCache){
final long maxMemory = Runtime.getRuntime().maxMemory();
//Use ... of available memory for List Notes thumb cache
return (int) (maxMemory * partOfTotalFreeMemoryToUseAsCache);
}

下面是我在适配器中使用它获取缓存图像的方法:

byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);

以及如何将其设置为缓存在后台线程(常规的 AsyncTask)中:

BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes);

我的应用程序的目标 API 19 + ,所以设备不老,这些部分的可用内存是足够好的缓存在我的情况下(1% 和3%)。

有趣的事实: Android 没有任何 API 或其他技巧来获取分配给应用程序的内存量,它是根据各种因素动态计算的。


另外,我使用一个静态类字段来保存一个缓存,但是根据最新的 Android 指南,建议使用 ViewModel 体系结构组件来保存缓存。

没有任何限制了,至少如果你去 NDK。为什么?请记住,Android 在历史上来自于嵌入式设备世界,在那里每个应用程序都有明确的简单任务要做,往往根本不允许动态内存使用。

它不被认为是一个通用的系统。我们仍然可以看到这个古老时代的许多设计工件,它们在“真正的电脑”上从来没有意义,这也是为什么 iOS 有那么多比安卓更好的应用程序的原因,它设计得更好,更容易为用户驱动的任务编程。

在应用程序设计中,重要的是您的活动对“ onLowMemory”信号反应良好。

现在,我正在工作的应用程序和三星超 S21,我正在使用(甚至有16 GB 的内存可用。.)不允许我使用超过500MB 的这个应用程序,甚至与 android: largeHeap = “ true”在清单中。