1、基本单位Page
Android是基于Linux操作系统,其内存基本单位称为:Page,默认4K为一个page。因此内存回收和分配的时候一般以4k进行处理,但是并不意味着所有的数据都是4k对齐的。
2、用户态和内核态
Android内存分用户态和内核态:
用户态:只能受限的访问内,所有app都是运行在用户态上的。
内核态:cpu可以访问内存的所有数据。
内核态的内存,用户态是严格不许访问的,例如一些Error Access,可能是指针飘到内核态上了。
3、内存杀手
Android有一个内存管理工具:Low Memory Killer,当内存不足时,会清理内存,在Android上常见的一些后台app消失,一些手机服务消失,手机重启或者是app崩溃闪退等都和它有关。
4、Android应用分层
首先我们来了解下Android的应用分层,这也是杀手的追杀路线(会从最底层往上杀)
Native | 系统内核,例如adbd |
System | 系统级应用,例如system server |
Persistent | 用户级应用,例如电话,蓝牙,wifi |
Foreground | 前台应用,当前正在使用的Activity |
Perceptible | 辅助类应用,例如搜索,音乐,键盘 |
Service | 一些驻后台的线程服务,例如云服务,垃圾回收 |
Home | 桌面 |
Previous | 上一个使用的应用 |
Cached | 后台应用 |
若此时我们的手机内存不足,杀手会一层层的从下往上杀,直到内存足够为止。同时每杀一层都会造成一定的现象,例如:
- Cached或Previous被杀,会导致再次使用之前应用的时候,应用重启。
- Home被杀导致桌面图标重建,或者壁纸不见了。
- Perceptible被杀会导致音乐停止等。
- Foreground被杀导致当前应用闪退。
- System被杀,就会导致手机重启。
- Native属于系统本身,因此是无法杀到的。
因此通过这些现象,我们就可以了解自己的app到底对内存的使用到了一个什么程度。例如使用自己app时,再返回上个app时导致上个app重启,说明杀手已经杀到了Previous层。
5、内存指标
首先我们要了解在计算app使用了多少内存时,系统需要统计共享页面(shared pages)。App在访问同一个service或者library的时候会共享内存页面。比如,Google地图和一个游戏app可能会共享一个定位服务。
常见的内存指标有如下三个
Resident Set Size(RSS) | 当前app所占用的所有内存,如果你的app通过Google Play Services分配了内存,那这部分内存也归你所有。(例如上面的例子中定位服务所占的内存就归自己app所有) |
Proportional Set Size(PSS) | 与RSS不同,通过Google Play Services分配的内存会平摊到所有呼叫这个服务的app上。(例如上面例子中定位服务所占的内存就会平摊到所有使用到的app上) |
Unique Set Size(USS) | 只有app自己占得内存,不算Google Play Services分配的内存(例如上面例子中,就不算算上定位服务所占的内存) |
一般来说内存占用大小有如下规律:RSS >= PSS >= USS