作者:林冠宏 / 指尖下的幽灵

掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

博客:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities

回答内存管理类面试问题可以说出下面这些内容,加分。


前言: 站在巨人的肩膀上,总结此文。

目录:

  • Java runtime 三个计算内存函数
  • OOM 的说法,为什么大型游戏能申请那么多内存?
  • 如何绕过dalvikvm heap size的限制 ?
  • Bitmap分配在native heap还是dalvik heap上?

1,Java runtime 三个计算内存函数:

maxMemory

获取当前 APP 最大能够申请的内存,在 Java Heap 部分。

totalMemory

获取当前 APP 已经从系统拿到的内存,包含使用上了的和没有用上的,因为一般申请会申请多一部分,它总是慢慢按需要从系统拿取。

freeMemory

获取当前 APP 拿到的内存中,还没用上的,即是可以被 gc 回收的。

计算此刻 APP 在 Java Heap 层次已经使用了的内存 usedMemory


usedMemory = totalMemory - freeMemory

2,OOM 的说法,为什么大型游戏能申请那么多内存?

在不同的 Android 系统版本中,OOM 的判断是不一样的。

  • 通俗来说,OOM 是当前进程共申请的内存综和超过一个限制,而被抛出。

  • 专业来说,Android为每个进程设置Dalvik Heap Size阈值,这个阈值在不同的设备上会因为RAM大小不同而各有差异。如果APP想要分配的内存超过这个阈值,就会发生OOM。

  • Android 3.x以前,Bitmap分配在Native heap中,而在3.x之后,Bitmap分配在Dalvik或ART的Java heap中。

  • Android 2.x系统,当dalvik allocated + native allocated + 新分配的大小 >= dalvik heap 最大值时候就会发生OOM,也就是说在2.x系统中,考虑native heap对每个进程的内存限制。

  • Android 3.x系统,废除了native的计数器,类似bitmap的分配改到dalvik的java heap中申请,只要allocated + 新分配的内存 >= dalvik heap 最大值的时候就会发生OOM(art运行环境的统计规则还是和dalvik保持一致),也就是说在3.x系统中,不考虑native heap对每个进程的内存限制,native heap只会收到本机总内存(包括RAM以及SWAP区或分页文件)的限制。

这也是为什么有些APP(比如大型游戏)可以超过 Dalvik Heap Size 这个值?那是因为Java内存又分为Java Heap和Native Heap,3.X 后 Native Heap是不受该值约束的。像C/C++的内存都是在Native Heap中分配的。另外Bitmap是在Java Heap中分配的,我们开发过程中经常遇到由Bitmap引起的OOM,这就是一个例子。

3,如何绕过dalvikvm heap size的限制 ?

  • 创建子进程,上面说了,内存分配按进程来。再使用进程通讯

创建一个新的进程,那么我们就可以把一些对象分配到新进程的heap上了,从而达到一个应用程序使用更多的内存的目的,当然,创建子进程会增加系统开销,而且并不是所有应用程序都适合这样做,视需求而定。

创建子进程的方法:使用android:process标签

  • 按不同的系统版本,使用 jni 在native heap上申请空间(推荐使用)

3.X 后的系统 native heap的增长并不受dalvik vm heapsize的限制,只要RAM有剩余空间,程序员可以一直在native heap上申请空间,当然如果 RAM快耗尽,memory killer会杀进程释放RAM。大家使用一些软件时,有时候会闪退,就可能是软件在native层申请了比较多的内存导致的。比如,我就碰到过UC web在浏览内容比较多的网页时闪退,原因就是其native heap增长到比较大的值,占用了大量的RAM,被memory killer杀掉了。

  • 使用显存(操作系统预留RAM的一部分作为显存)

使用OpenGL textures等API,texture memory不受dalvik vm heapsize限制,这个我没有实践过。再比如Android中的GraphicBufferAllocator申请的内存就是显存。

4,Bitmap分配在native heap还是dalvik heap上?

上面说了,不同的系统版本不同,那么在 3.X 及其之后,为什么在 java heap 而不是在 native heap 。请看下面源码。

主要的文件

framework/base/graphic/java/Android/graphics/BitmapFactory.java
framework/base/core/jni/Android/graphics/BitmapFactory.cpp
framework/base/core/jni/Android/graphics/Graphics.cpp

BitmapFactory.java 里面有几个decode***方法用来创建bitmap,最终都会调用:


private staticnative Bitmap nativeDecodeStream(InputStream is, byte[] storage,Rect padding,Options opts);

nativeDecodeStream()会调用到BitmapFactory.cpp中的deDecode方法,最终会调用到Graphics.cppcreateBitmap方法。

createBitmap方法的实现:

jobjectGraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
boolisMutable, jbyteArray ninepatch, int density)
{
SkASSERT(bitmap);
SkASSERT(bitmap->pixelRef()); jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)),
buffer, isMutable, ninepatch,density);
hasException(env); // For the side effectof logging.
return obj;
}

从代码中可以看到bitmap对象是通过env->NewOject(...)创建的,到这里疑惑就解开了,bitmap对象是虚拟机创建的,JNIEnv的NewOject方法返回的是java对象,并不是native对象,所以它会分配到dalvik heap中。

浅谈 maxMemory , totalMemory , freeMemory 和 OOM 与 native Heap的更多相关文章

  1. Android性能优化的浅谈

    一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...

  2. 浅谈Android应用性能之内存

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 文/ jaunty [博主导读]在Android开发中,不免会遇到许多OOM现象,一方面可能是由于开 ...

  3. 浅谈开源项目Android-Universal-Image-Loader(Part 3.1)

    本文转载于:http://www.cnblogs.com/osmondy/p/3266023.html 浅谈开源项目Android-Universal-Image-Loader(Part 3.1) 最 ...

  4. 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署

    谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...

  5. 朱晔的互联网架构实践心得S2E6:浅谈高并发架构设计的16招

    朱晔的互联网架构实践心得S2E6:浅谈高并发架构设计的16招 概览 标题中的高并发架构设计是指设计一套比较合适的架构来应对请求.并发量很大的系统,使系统的稳定性.响应时间符合预期并且能在极端的情况下自 ...

  6. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  7. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  8. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  9. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

随机推荐

  1. bootstrap-table 表格加载中....处理

    $('#table').bootstrapTable({data:[]}); $('#table').bootstrapTable("showLoading"); ajax数据加载 ...

  2. JavaScript ECMAScript版本介绍

    1. 介绍 1.1 什么是ECMAScript ECMAScript,简称ES,是由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers ...

  3. scrapy_css

    css选择器标准格式:reponse.css(css选择器::获取值) css选择器有哪些? *            选择所有节点 #id         选择id的节点 .container    ...

  4. springmvc配置文件配置的事务作用范围

    作用于service,不是controller,也不是mapper.所以,要保证原子性,就放在一个serviceimpl里,而不要放在一个controller 里 第一次与数据库打交道时,事务开启,s ...

  5. 【转】十分有用的linux shell学习总结

    在最近的日常工作中由于经常会和Linux服务器打交道,如Oracle性能优化.我们 数据采集服务器的资源利用率监控,以及Debug服务器代码并解决其效率和稳定性等问题.因此这段时间总结的有关Linux ...

  6. 【转】iptables 命令介绍

    iptables 防火墙可以用于创建过滤(filter)与NAT规则.所有Linux发行版都能使用iptables,因此理解如何配置iptables将会帮助你更有 效地管理Linux防火墙.如果你是第 ...

  7. Sql Server的艺术(三) SQL聚合函数的应用

    SQL提供的聚合函数有求和,最大值,最小值,平均值,计数函数等. 聚合函数及其功能: 函数名称 函数功能 SUM() 返回选取结果集中所有值的总和 MAX() 返回选取结果集中所有值的最大值 MIN( ...

  8. IIS与Apache禁止IP地址直接访问网站

    一.IIS 防止恶意域名指向解决方法 首先单击"开始"-"设置"-"控制面板"-"管理工具",找到"Inter ...

  9. 树莓派用U盘安装系统

    * 需要使用Raspbian / Raspbian Lite或更高版本的2017-04-10版本 *不会SD卡装系统? 1.  先用装好Raspbian系统的SD卡启动 在命令行输入    echo ...

  10. VS工程中的Windows.h

    才发现这个Windows.h是有些奥秘的,不是随便引用就可以的. 1,C++工程,头文件引用要讲求一定顺序.如果cpp文件先引用a.h,再引用b.h,则后者自动包含a.h.这一点很重要. 2,Wind ...