android 游戏内存,如何「偷」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来对其进行读写等操作:

MemoryFile memoryFile = new MemoryFile(null, inputStream.available());

memoryFile.allowPurging(false);

OutputStream outputStream = memoryFile.getOutputStream();

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的值:

phpHnU8q1.1456233464.jpg

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

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

phpnOkhFW.1456233482.jpg

而且这里我也算过,也是不算入Native Heap中的,另外,这个时候去系统设置里面看进程的内存占用,也可以看出来其实并没有计入Ashmem的内存的。这个应该是android的一个BUG,但是我搜了一下并没有搜到对应的issue,搞不好这里也可能是一个feature。

而在大名鼎鼎的Fresco当中,他们也有用到这个bug来避免在decode bitmap的时候,将文件的字节读到Java堆中,使用了MemoryFile,并利用了这个BUG然这部分内存不算入app中,这里分别对应了Fresco中的GingerbreadPurgeableDecoder和KitKatPurgeableDecoder,Fresco在decode图片的时候会在4.4和4.4以下的系统中分别使用这两个不同的decoder。从这个地方可以看出来,使用MemoryFile,在4.4以下的系统当中,可以帮我们的app额外”偷”一些内存,并且可以不计入app的内存当中

Summary

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

References

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

Android Kernel Features(Ashmem)

加入GAD的核心用户QQ群:484290331,各类活动奖励任你拿,最新资讯任你读,众多教学任你免费学,如此好地方赶紧加入吧!另VR专属群:476511561,专业VR技术分享,专业导师指导为你答疑解惑,大型小型活动奖励等你拿,免费学习赚奖励的天地,欢迎你加入哟!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值