专栏首页Android进阶之路Android为每个应用分配多少内存?如何进行性能调优
原创

Android为每个应用分配多少内存?如何进行性能调优

熟悉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时为低内存运行");
}

那么如何进行APP应用的内存优化呢?

1.用户体验及资源消耗优化

image.png

2.代码框架结构优化

image.png

3.屏幕适配及代码质量调优

image.png

喜欢我的文章可以点赞+关注我的【个人主页】获取免费资料,后续我将继续分享更多Android技术干货,感谢支持!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 互联网“寒冬”不想被辞退,Android程序员该如何应对?

    最近,在气候转凉的同时,互联网领域也是寒气逼人,许多人担心互联网寒冬的到来。其实,寒冬来了又怎样?关键在于你怎么看待互联网寒冬。

    Android架构
  • 三条有效的实战经验助你成为移动互联架构师!

    架构师的职责应该是立足于技术和业务之间的中间角色或者平衡点, 在针对业务深刻理解的基础上,针对业务中存在诸多变数,挑选适合的技术架构和技术方案。

    Android架构
  • Kotlin入门潜修之类和对象篇—泛型及其原理

    如果我们了解java中的泛型,那么本篇文章提到的kotlin泛型我们也不会陌生。但是如果之前没有接触过泛型或者没有真正理解泛型,本篇文章理解起来可能有些困难,不...

    Android架构
  • CM: 使用ICF node实现对附件的读取

    1. 创建一个新的class,实现interface IF_HTTP_EXTENSION:

    Jerry Wang
  • Moodle进入Web Platform Installer 2.0

    微软Web平台安装程序2.0(Web PI)是一个免费工具,用来简化微软Web平台的下载、安装和最新更新,这包括IIS、SQL Server快递版、.NET框架...

    张善友
  • Python在应用层实现UDP协议的可靠传输

    使用UDP协议传输文件,在应用层实现可靠传输,避免传输层不保序和可能丢包造成的不可靠传输问题。

    Python小屋屋主
  • TNBC分型研究的来龙去脉(逆向收费读文献2019-09)

    2年前,考虑到科研路的艰难,我组建了文献阅读小组,广邀粉丝参与,从自身做起,开始学习及分享!感兴趣可以点击下面的链接跳转去了解详情:

    生信技能树
  • 使用Sublime Text 3作为Py

     Sublime Text 3是一款非常好用的编辑器,用它作为Python编辑器时,需要解决中文支持问题,常见问题有两个,一是中文乱码问题,二是运行时Pytho...

    py3study
  • Dubbox框架与Zookeeper入门之DEMO

    (1)创建Maven工程(WAR)dubboxdemo-service ,在pom.xml中引入依赖

    一点博客
  • 云采用成功的10个最佳实践

    虽然将业务迁移到云平台是一件好事,但企业必须谨慎行事。无论企业是处理多个工作负载还是产品组合,从内部部署到基于云计算的IT转型不只是为了了解技术。而成功采用云计...

    静一

扫码关注云+社区

领取腾讯云代金券