浅谈 maxMemory , totalMemory , freeMemory 和 OOM 与 native Heap
作者:林冠宏 / 指尖下的幽灵
掘金: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.cpp
的createBitmap
方法。
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
中。
转载于:https://www.cnblogs.com/linguanh/p/8496002.html
浅谈 maxMemory , totalMemory , freeMemory 和 OOM 与 native Heap相关推荐
- 浅谈Java锁,与JUC的常用类,集合安全类,常用辅助类,读写锁,阻塞队列,线程池,ForkJoin,volatile,单例模式不安全,CAS,各种锁
浅谈JUC的常用类 JUC就是java.util.concurrent-包下的类 回顾多线程 Java默认有几个线程? 2 个 mian.GC Java 真的可以开启线程吗? 开不了,点击源码得知:本 ...
- java方法区对象类型_浅谈Java内存区域与对象创建过程
一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...
- java手动回收_浅谈java是如何做资源回收补救的
学习java的过程,我们经常谈论一个对象的回收,尤其是资源类型,如果没有显示的关闭,对象就被回收了,说明出现了资源泄漏.java本身为了防止这种情况,做了一些担保的方式,确保可以让未关闭的资源合理回收 ...
- android 存储空间监控,浅谈 Android 内存监控(中)
前言 在上篇 浅谈 Android 内存监控(上) 中,我们聊了 LeakCanary,微信的 Matirx 和美团的 Probe,它们各自有不同的应用场景,例如,在开发测试环境,我们会偏向用 Lea ...
- 高通android逆向分析,浅谈Android高通(Qualcomm)和联发科(MTK)平台
一款CPU好不好是要从多个方面考虑的,并不是说简简单单看一个主频.几个核心数就完了,更重要的是它的综合实力到底有多强,这里面当然也会牵扯到价格问题,性能相似当然是便宜的获胜,这是毋庸置疑的. 事实上, ...
- Java开发的B/S程序生成并向客户端发送excel文件:浅谈MIME
Java开发的B/S程序生成并向客户端发送excel文件:浅谈MIME 1.定义 MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型.是设定 ...
- 浅谈Metaspace内存溢出原因及JVM参数设置
浅谈Metaspace内存溢出原因及JVM参数设置 1.Metaspace内存溢出(oom) 日志 原因分析 从Java8开始,Java中的内存模型引入了一个称为元空间(Metaspace)的新内存区 ...
- 浅谈MySQL存储引擎-InnoDBMyISAM
浅谈MySQL存储引擎-InnoDB&MyISAM 存储引擎在MySQL的逻辑架构中位于第三层,负责MySQL中的数据的存储和提取.MySQL存储引擎有很多,不同的存储引擎保存数据和索引的方式 ...
- 【大话设计模式】——浅谈设计模式基础
初学设计模式给我最大的感受是:人类真是伟大啊!单单是设计模式的基础课程就让我感受到了强烈的生活气息. 个人感觉<大话设计模式>这本书写的真好.让貌似非常晦涩难懂的设计模式变的生活化.趣味化 ...
最新文章
- 《.NET与设计模式》学习(一)
- 电大在线计算机考试,最新电大《计算机》考试题.doc
- set和multiset容器
- 浅谈c++中结构体和共用体的区别
- 敏捷开发用户故事系列之七:用户故事与MVC
- 大学生就业新神器 网络电话“通”职场
- 算法8-排序-基数排序
- 【知识图谱系列】六篇2020年知识图谱预训练论文综述 | 30页汇报ppt免费获取 | GCC,GraphCL,DGI,InfoGraph等模型
- 前端调试,模拟数据利器之Mock Server使用教程来啦~
- 神经网络的深度、宽度
- 目瞪口呆,4款1M不到的实用软件,颠覆你的认知
- 计算机打开管理闪退,win10任务管理器闪退怎么解决-解决win10任务管理器闪退的方法 - 河东软件园...
- 因为改 UOM conversion 导致库存数量和財务上的数据错误
- icp许可证怎么申请
- Error launching IEDA-启动IDEA报错解决(创建JVM失败提示)
- Excel快速核对两张表格
- Deepin15.8系统下安装QorIQ Linux SDK v2.0 yocto成功完美运行的随笔
- linux 隐藏命令参数,linux – 在ps中隐藏命令的参数
- 【心慈喜讯】“心”启航青少年心理健康支持项目成功入选广州市海珠区“慈泉杯”社会组织公益创投活动
- win10系统AMD显卡OBS录屏黑屏解决方法