应用程序可以使用的最大 RAM 量是多少?

Posted

技术标签:

【中文标题】应用程序可以使用的最大 RAM 量是多少?【英文标题】:What is the maximum amount of RAM an app can use? 【发布时间】:2013-09-11 14:29:09 【问题描述】:

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

我想知道的:

最大内存量是多少(单位为兆字节 / as android 应用(非系统应用)可以使用的总 RAM 的 百分比Android 版本之间有什么区别吗? 设备的制造商有什么不同吗?

最重要的是:

什么被考虑/它取决于什么,当涉及到系统确定应用程序在运行时可以使用多少 RAM 时(假设每个应用程序的最大内存不是静态数字)?

到目前为止我所听到的(直到 2013 年):

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

是什么让我非常好奇:

这两个限制都非常低。

我最近刚刚下载了Android Task Manager 来检查我的设备内存。我注意到有些应用程序使用了大约 40-50 MB 的 RAM,这显然比提到的最大 RAM 使用量(比如说 32 MB)要多。那么,Android 是如何确定应用程序可以使用多少 RAM 的呢?应用程序怎么可能超过这个限制?

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

免责声明:我与 Android 任务管理器应用没有任何关联。

【问题讨论】:

【参考方案1】:

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

它不被视为通用系统。我们仍然可以看到很多古代的设计作品,这些作品在“真正的计算机”上从来没有意义,这也是为什么 ios 拥有比 android 更好的应用程序的原因,它被设计得更好,更容易为用户驱动的任务编程.

应用设计中的重要一点是您的活动对“onLowMemory”信号反应良好。

【讨论】:

【参考方案2】:

现在,我正在开发一个应用程序,而我正在使用的三星 Ultra S21(即使有 16GB 的可用内存..)也不允许我为这个应用程序使用超过 500MB 的空间,即使使用 android:largeHeap=" true”在 Manifest 中。

【讨论】:

【参考方案3】:

现在是 2018 年底,所以情况发生了变化。

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

官方文档中还有here is a great article,其中包含有关如何使用 Memory Profiler 的详细说明,它可以让您深入了解内存管理。

但在大多数情况下,您的常规 Android Profiler 对您来说就足够了。

通常,应用开始时分配的 RAM 为 50Mb,但当您开始在内存中加载一些照片时,它会立即跃升至 90Mb。当您使用带有预加载照片(每张 3.5Mb)的 ViewPager 打开 Activity 时,您可以在几秒钟内轻松获得 190Mb。

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

我能给出的最佳建议是遵循指南和最佳实践,使用***库进行图像加载(Glide、Picasso),你会没事的。


但是,如果您需要定制某些内容,并且您确实需要知道可以手动分配多少内存,您可以获取总可用内存并从中计算出预先确定的部分(以 % 为单位)。 就我而言,我需要将解密的照片缓存在内存中,这样我就不需要在每次用户滑过列表时都解密它们。

为此,您可以使用现成的LruCache class。它是一个缓存类,它自动跟踪您的对象分配了多少内存(或实例数),并根据它们的使用历史删除最旧的以保留最新的。 Here is 一个很好的使用教程。

就我而言,我创建了 2 个缓存实例:用于拇指和附件。 通过单例访问使它们保持静态,以便它们在整个应用程序中全局可用。

缓存类:

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;


这是我计算可用空闲 RAM 以及我可以从中消耗多少的方法:

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+ 为目标,因此设备不旧,并且这些可用 RAM 部分在我的情况下足以用于缓存(1% 和 3%)。

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


附:我正在使用静态类字段来保存缓存,但根据最新的 Android 指南,建议为此使用 ViewModel architecture component。

【讨论】:

“有趣的事实:Android 没有任何 API 或其他黑客来获取分配给您的应用程序的内存量”这是错误的。当然有,但是在应用程序的 JNI/Linux 层中。 Android (Java) 本身只是一个夸张的 GUI 库。【参考方案4】:

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

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

【讨论】:

驱动器url请求访问权限【参考方案5】:

Android 应用程序(非系统应用程序)可以使用的最大内存量是多少(以 MB 为单位/占总 RAM 的百分比)?

这因设备而异。 getMemoryClass() on ActivityManager 将为您提供运行代码的设备的值。

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

是的,只要操作系统要求多年来不断增加,设备必须进行调整以匹配。

设备制造商是否存在差异?

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

在确定应用可以使用多少 RAM 时,会考虑哪些“附带因素”?

我不知道“附带因素”是什么意思。

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

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

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

您假设该应用的作者知道他在做什么。考虑到memory usage of an app is difficult for a core Android engineer to determine,我不认为有问题的应用程序一定会提供特别准确的结果。

话虽如此,本机代码 (NDK) 不受堆限制。而且,从 Android 3.0 开始,应用程序可以请求“大堆”,通常在数百 MB 范围内,但对于大多数应用程序来说,这被认为是糟糕的形式。

此外,我注意到我的一些应用程序在使用大约 30-40 兆字节时崩溃并出现 OutOfMemoryException。

请记住,Android 垃圾收集器不是压缩垃圾收集器。例外确实应该是CouldNotFindSufficientlyLargeBlockOfMemoryException,但这可能被认为太罗嗦了。 OutOfMemoryException 表示您无法分配您请求的块,并不是说您已经完全耗尽了堆。

【讨论】:

我无法理解表格,我有 Xperia X mobile,其分辨率约为 1080 x 1920,即大分辨率,而另一台设备三星 Tab 4 的分辨率为 800 x 1280,因此占用相同的内存,请指导我,因为手机带有3GB RAM,而tab带有1.5GB RAM,所以平板电脑因为大屏幕而占用大量内存? @RahulMandaliya:我很抱歉,但我不明白你的担忧或它与这个问题有什么关系。您可能希望打开一个单独的 Stack Overflow 问题,详细解释您的担忧。

以上是关于应用程序可以使用的最大 RAM 量是多少?的主要内容,如果未能解决你的问题,请参考以下文章

可以从 sql server 中的 sproc 返回到 ADO.NET 应用程序的最大数据量是多少

Adobe AIR 可以使用的最大内存量是多少?

通过 Python 函数跟踪*最大*内存使用情况

面试官问:你们服务最大的并发量是多少?

iOS 应用程序可以泄漏的最大内存量

运行内存RAM是啥