如何「偷」Android 的内存?

之前在做一个内存优化的时候,使用到了MemoryFile,由此发现了MemoryFile的一些特性以及一个非常trickly的使用方法,因此在这里记录一下。

What is it

MemoryFile是android在最开始就引入的一套框架,其内部实际上是封装了android特有的内存共享机制Ashmem匿名共享内存,简单来说,Ashmem在Android内核中是被注册成一个特殊的字符设备,Ashmem驱动通过在内核的一个自定义slab缓冲区中初始化一段内存区域,然后通过mmap把申请的内存映射到用户的进程空间中(通过tmpfs),这样子就可以在用户进程中使用这里申请的内存了,另外,Ashmem的一个特性就是可以在系统内存不足的时候,回收掉被标记为”unpin”的内存,这个后面会讲到,另外,MemoryFile也可以通过Binder跨进程调用来让两个进程共享一段内存区域。由于整个申请内存的过程并不再Java层上,可以很明显的看出使用MemoryFile申请的内存实际上是并不会占用Java堆内存的。

MemoryFile暴露出来的用户接口可以说跟他的名字一样,基本上跟我们平时的文件的读写基本一致,也可以使用InputStream和OutputStream来对其进行读写等操作:


  1. MemoryFile memoryFile = new MemoryFile(null, inputStream.available()); 
  2.  
  3. memoryFile.allowPurging(false); 
  4.  
  5. OutputStream outputStream = memoryFile.getOutputStream(); 
  6.  
  7. outputStream.write(1024);  

上面可以看到allowPurging这个调用,这个就是之前说的”pin”和”unpin”,在设置了allowPurging为false之后,这个MemoryFile对应的Ashmem就会被标记成”pin”,那么即使在android系统内存不足的时候,也不会对这段内存进行回收。另外,由于Ashmem默认都是”unpin”的,因此申请的内存在某个时间点内都可能会被回收掉,这个时候是不可以再读写了

Tricks

MemoryFile是一个非常trickly的东西,由于并不占用Java堆内存,我们可以将一些对象用MemoryFile来保存起来避免GC,另外,这里可能android上有个BUG:

在4.4及其以上的系统中,如果在应用中使用了MemoryFile,那么在dumpsys meminfo的时候,可以看到多了一项Ashmem的值:

可以看出来虽然MemoryFile申请的内存不计入Java堆也不计入Native堆中,但是占用了Ashmem的内存,这个实际上是算入了app当前占用的内存当中

但是在4.4以下的机器中时,使用MemoryFile申请的内存居然是不算入app的内存中的:

 

而且这里我也算过,也是不算入Native Heap中的,另外,这个时候去系统设置里面看进程的内存占用,也可以看出来其实并没有计入Ashmem的内存的

这个应该是android的一个BUG,但是我搜了一下并没有搜到对应的issue,搞不好这里也可能是一个feature

而在大名鼎鼎的Fresco当中,他们也有用到这个bug来避免在decode bitmap的时候,将文件的字节读到Java堆中,使用了MemoryFile,并利用了这个BUG然这部分内存不算入app中,这里分别对应了Fresco中的GingerbreadPurgeableDecoder(https://github.com/facebook/fresco/blob/master/imagepipeline/src/main/java/com/facebook/imagepipeline/platform/GingerbreadPurgeableDecoder.java)和KitKatPurgeableDecoder(https://github.com/facebook/fresco/blob/master/imagepipeline/src/main/java/com/facebook/imagepipeline/platform/KitKatPurgeableDecoder.java),Fresco在decode图片的时候会在4.4和4.4以下的系统中分别使用这两个不同的decoder

从这个地方可以看出来,使用MemoryFile,在4.4以下的系统当中,可以帮我们的app额外”偷”一些内存,并且可以不计入app的内存当中

Summary

这里主要是简单介绍了MemoryFile的基本原理和用法,并且阐述了一个MemoryFile中一个可以帮助开发者”偷”内存的地方,这个是一个非常trickly的方法,虽然4.4以下使用这块的内存并不计入进程当中,但是并不推荐大量使用,因为当设置了allowPurging为false的时候,这个对应的Ashmem内存区域是被”pin”了,那么在android系统内存不足的时候,是不能够把这段内存区域回收的,如果长时间没有释放的话,这样子相当于无端端占用了大量手机内存而又无法回收,那对系统的稳定性肯定会造成影响

References

1. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

  http://blog.csdn.net/luoshengyang/article/details/6664554

2. Android Kernel Features(Ashmem)

  http://elinux.org/Android_Kernel_Features#ashmem

本文作者:佚名

来源:51CTO

时间: 2024-09-17 01:47:17

如何「偷」Android 的内存?的相关文章

当网络出现「垄断」 创业天堂就不再有3.0

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断淘宝客 站长团购 云主机 技术大厅 这几天部落格发生大当机,网址转来转去,现在还在忙.若您昨天或今天来看却进不来,在此与您致上最高的歉意,也谢谢您今天再度光临敝小站. 平常写部落格这么简单,写一篇文章,放到上面去,大家就看得到,但昨天的感受,像是喉咙被掐住,当电话传来机房客服人员很没水平的叫我「明天再打电话来」,真的有一种很深的无力感──我的网站虽然是「我的」,但碰到这

程序员经常说的「设计模式」到底是什么?

当程序员说去「设计模式」时,你是否会一脸懵逼,到底什么是设计模式呢? 很多人应该听说过设计模式(Design pattern),又或多或少的看过或用过设计模式,但是实际用在开发过程中总有点心有余而力不足的感觉.那肯定是对设计模式的理解有少许偏差或者不够深入.先不谈某种具体的模式,先来看看什么是设计模式? 什么是设计模式? 设计模式是一套代码设计「 经验的总结 」.项目中「 合理的 」运用设计模式可以「 巧妙的解决很多问题 」. 经验的总结:抱着「代码虐我千百遍,我待代码如初恋」的心态,最终得出来

让「折腾」这件事变得更好玩一些:在iPad上运行PC系统

本文讲的是让「折腾」这件事变得更好玩一些:在iPad上运行PC系统,在 iOS 设备上运行 PC 系统古已有之,不但有各种越狱插件,还有很多偷偷上架在 App Store 里的软件.但自从 iOS 加强对设备内文件的保护之后,由于不再能通过特殊软件访问到除 iTunes 共享文件夹之外的其他文件,那些靠关闭文件共享向苹果隐藏身份的 App 已经销声匿迹了. 那现在我们是否还有办法在不越狱的情况下继续在 iOS 上运行 PC 系统呢?幸运的是,这些曾经可用的工具都是开源的,在苹果开放了 Xcode

jvm系列(十):如何优化Java GC「译」

本文由CrowHawk翻译,地址:如何优化Java GC「译」,是Java GC调优的经典佳作. Sangmin Lee发表在Cubrid上的"Become a Java GC Expert"系列文章的第三篇<How to Tune Java Garbage Collection>,本文的作者是韩国人,写在JDK 1.8发布之前,虽然有些地方有些许过时,但整体内容还是非常有价值的.译者此前也看到有人翻译了本文,发现其中有许多错漏生硬和语焉不详之处,因此决定自己翻译一份,供大

为何不要用「h5」这个简称?

  最近发现好多人喜欢将 HTML5 说成 h5,甚至是代指移动端的 Web Page 或者 Web App.虽然说起来朗朗上口,但是小编真的不建议这样来使用. 小编很早之前做过一个关于「h5 这个说法你的感受」的调查,总共有 552 位粉丝参与,最终结果是:有 16.7% 的人认为「很好」,37.5% 的认为「无所谓」,有 45.8% 的人认为「不喜欢」.那究竟为什么会有那么多人不喜欢「h5」这个简称呢? 「h5」这个简称非常不专业,容易造成误导. 与 JavaScript 被简称为「JS」不

Android手机内存中文件的读写方法小结

  Android手机内存中文件的读写方法小结         这篇文章主要介绍了Android手机内存中文件的读写方法,实例总结了Android针对文件读写操作的相关技巧,非常具有实用价值,需要的朋友可以参考: 如何对手机内存中的文件数据进行读写呢? Context提供了领个方法来打开该应用程序的数据文件夹中的文件I/O流,具体如下: ? 1 FileInputStream openFileInput(String name) 打开应用程序的数据文件夹下的name文件对应的数据流 ? 1 Fi

对初阶体验设计师「影响力」构建的浅思

  国内一些刚刚从业.甚至已经从业好几年的用户体验设计师,在做了一段时间设计后,会或多或少产生一些困惑:自己似乎缺少足够的话语权和影响力,总是被产品经理和技术团队牵着鼻子走;花大量时间做一些技术含量不高的「体力活」,却又得不到对等的回报;产品上线了成功了,大家都觉得是产品经理或者技术团队的功劳(尤其是一些UI存在感不强甚至没有UI的产品),而有些忽视UED在背后的付出--于是很多渴望有更多「影响力」的设计师,最终纷纷选择转为产品经理,虽然有一些人在新的岗位做得很棒.让我心悦诚服,但我却从来不觉得

如何把谷歌的「思源黑体」作为WEBFONT使用?

  想让你的网站瞬间提升质感?试试谷歌和Adobe联合推出的「思源黑体」!现在只要加入一段 Typekit 程序代码,就可以把思源黑体作为网页字体(Webfont)使用了,附上具体的使用教程,来收! 相信大家对「思源黑体(Source Han Sans)」都不陌生,这是 Adobe 和 Google 合作,于 2014 年推出的开放原始码免费字型,提供七种粗细设定,完整支持日文.韩文.繁体及简体中文,有鉴于免费中文字型选择不多,在开发上也颇具难度,一推出便受到许多人关注,修改版字型也陆续出现,例

20个简单易上手堪称「神器」的可视化工具

  国外的可视化行业发展得相当成熟,这催生了不少在线信息图表制作工具,介绍比较好用的几个,利用它们,五分钟你就可以做出一张超屌的信息图表: 1]infogr.am 这是较早的一个在线制作工具,亮点是支持实时数据刷新,而且制作的信息图表支持在多终端展示. 2]Venngage 这款工具的亮点是自带超多免费模板,超多的版式选择,配色潮流大胆. 3]Piktochart 跟上一款非常相似,但免费模板不够多~ 用多了你会发现,这些傻瓜型工具的功能都大同小异,他们唯一的区别就是:各有各骚气的模板,各有各屌