Android为每个应用分配多少内存?

2018-11-21 09:07:37
熟悉Android内存分配机制的朋友都知道,Android为每个进程分配内存时,采用弹性的分配方式,即刚开始并不会给应用分配很多的内存,而是给每一个进程分配一个“够用”的内存大小。

那Android到底为每个应用分配多少内存呢?我们可以实际测试一下:

以本人手上的努比亚NX510J手机为例:

    private void getMaxMemoryInfo(){
        Runtime rt = Runtime.getRuntime();
        long maxMemory = rt.maxMemory();
        Log.e("MaxMemory:", Long.toString(maxMemory/(1024*1024)));
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        Log.e("MemoryClass:", Long.toString(activityManager.getMemoryClass()));
        Log.e("LargeMemoryClass:", Long.toString(activityManager.getLargeMemoryClass()));
    }

输出结果为:

06-06 15:27:22.740 11917-11917/com.suning.myapp E/MaxMemory:: 192
06-06 15:27:22.740 11917-11917/com.suning.myapp E/MemoryClass:: 192
06-06 15:27:22.740 11917-11917/com.suning.myapp E/LargeMemoryClass:: 512

把AndroidManifest.xml中的application标签加上

<application
        ...
        android:largeHeap="true"
        ...>
        ...
</application>

输出结果为:

06-06 15:32:06.168 21973-21973/com.suningtang.myapp E/MaxMemory:: 512
06-06 15:32:06.168 21973-21973/com.suningtang.myapp E/MemoryClass:: 192
06-06 15:32:06.168 21973-21973/com.suningtang.myapp E/LargeMemoryClass:: 512

可以看到,设置largeHeap为true时, 通过rt.maxMemory();获取的值为512M。

因此,对于本人这台手机,系统正常分配的内存最多为192M;当设置largeHeap时,最多可申请512M。当超过这个值时,就会出现OOM了。

这个值是在哪设置的呢?查看/system/build.prop文件内容:

shell@NX510J:/ $ cat /system/build.prop | grep heap
dalvik.vm.heapsize=36m
   
dalvik.vm.heapstartsize=8m    ----起始分配内存
dalvik.vm.heapgrowthlimit=192m ---- 一般情况app申请的最大内存 dalvik.vm.heapsize=512m   ---- 设置largeheap时,App可用的最大内存dalvik.vm.heaptargetutilization=0.75  ---- GC相关
dalvik.vm.heapminfree=512k
dalvik.vm.heapmaxfree=8m     ----- GC机制相关

上面的标注了各参数的含义。

那ActivityManager的getMemoryClass()和getLargeMemoryClass()方法返回的的是哪里的值呢?

//ActivityManager.java

public int getMemoryClass() {
        return staticGetMemoryClass();
    }
    
    /** @hide */
    static public int staticGetMemoryClass() {
       
        String vmHeapSize = SystemProperties.get("dalvik.vm.heapgrowthlimit", "");
        if (vmHeapSize != null && !"".equals(vmHeapSize)) {
            return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
        }
        return staticGetLargeMemoryClass();
    }
    
    /**
     * Return the approximate per-application memory class of the current
     * device when an application is running with a large heap.  This is the
     * space available for memory-intensive applications; most applications
     * should not need this amount of memory, and should instead stay with the
     * {@link #getMemoryClass()} limit.  The returned value is in megabytes.
     * This may be the same size as {@link #getMemoryClass()} on memory
     * constrained devices, or it may be significantly larger on devices with
     * a large amount of available RAM.
     *
     * <p>The is the size of the application's Dalvik heap if it has
     * specified <code>android:largeHeap="true"</code> in its manifest.
     */
    public int getLargeMemoryClass() {
        return staticGetLargeMemoryClass();
    }
    
    /** @hide */
    static public int staticGetLargeMemoryClass() {
        String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
        return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length() - 1));
    }

上面的源码表明,getMemoryClass()和getLargeMemoryClass()方法最终读取的仍然是dalvik.vm.heapgrowthlimit和dalvik.vm.heapsize的值。而且,dalvik.vm.heapsize默认值为16M,这也是解释了google的原生OS默认值是16M了。而dalvik.vm.heapgrowthlimit和dalvik.vm.heapsize的值各个手机厂家的OS会对这个值进行修改,所以存在差异。

在App中获取内存信息

我们在应用中可以通过ActivityManager的MemoryInfo内部类获取内存信息,方法如下:

private void getMemoryInfo() {
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
    manager.getMemoryInfo(info);  
    Log.e("Memory","系统总内存:"+(info.totalMem / (1024*1024))+"M");
    Log.e("Memory","系统剩余内存:"+(info.availMem / (1024*1024))+"M");
    Log.e("Memory","系统是否处于低内存运行:"+info.lowMemory );
    Log.e("Memory","系统剩余内存低于"+( info.threshold  / (1024*1024))+"M时为低内存运行");
}




  • 2017-04-06 15:15:16

    PHP-FPM配置及使用总结

    PHP-FPM配置及使用总结: PHP-FPM是一个PHP FastCGI的管理器,它实际上就是PHP源代码的补丁,旨在将FastCGI进程管理引进到PHP软件包中,我们必须将其patch到PHP源代码中,然后再行编译才能使用。而现在我们可以在PHP 5.3.2及更新版本中直接开启并使用即可,因为PHP从该版本已经将其收入到软件包中,所以其不再是补丁包的存在了。

  • 2017-04-07 23:18:29

    mac 安装composer

    当你下载了 composer.phar 后,可以将它放在目录中,但每次当你建立新目录时,你必須再复制一个副本到新目录中,这样比较麻烦。所以最佳做法是将它放到 usr/local/bin 目录中中,成为全域指令。

  • 2017-04-12 10:52:35

    最全面的Android Webview详解

    现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝、京东、聚划算等等,如下图

  • 2017-04-12 11:22:43

    WebView你真的熟悉吗?看了才知道

    在Android手机中内置了一款高性能webkit内核浏览器,在SDK中封装为一个叫做WebView组件。下面总结一下使用webview遇到的那些事、那些坑。

  • 2017-04-12 11:28:14

    史上最全webview详解

    WebView在现在的项目中使用的频率应该还是非常高的。 我个人总觉得HTML5是一种趋势。找了一些东西,在此总结。 本篇最后有一个非常不错 的 Html5Activity 加载类,不想看的可以直接跳下载。

  • 2017-04-12 23:11:59

    Android Studio签名打包的两种方式

    给我们自己开发的app签名,就代表着我自己的版权,以后要进行升级,也必须要使用相同的签名才行。签名就代表着自己的身份(即keystore),多个app可以使用同一个签名。

  • 2017-04-13 10:57:08

    webstorm 怎么关闭jshint

    You need to configure the inspections in Settings/Editor/Inspections, then in the list on the right, find JavaScript/JavaScript validity issues. That worked for me to remove the Chai warnings. (I am using the WebStorm 11 EAP at the moment.)