Android 依托 Java 型虚拟机,OOM 是经常遇到的问题。那么在快达到 OOM 的时候,系统难道不能回收部分界面来达到缩减开支的目的?在系统内存不足的情况下,可以通过 AMS 及 LowMemoryKiller 杀优先级低的进程,来回收进程资源。但是这点对于前台 OOM 问题并没有多大帮助,因为每个 Android 应用有一个 Java 内存上限,比如 256 或者 512M,而系统内存可能有 6G 或者 8G。也就是说,一个 APP 的进程达到 OOM 的时候,可能系统内存还是很充足的,这个时候,系统如何避免 OOM 的呢?iOS 是会将不可见界面都回收,之后再恢复,Android 做的并没有那么彻底,简单说:对于单栈(TaskRecord)应用,在前台的时候,所有界面都不会被回收,只有多栈情况下,系统才会回收不可见栈的 Activity。注意回收的目标是不可见栈(TaskRecord)的 Activity。
Android 原生提供内存回收入口
Google 应该也是想到了这种情况,源码自身就给 APP 自身回收内存留有入口,在每个进程启动的时候,会同步启动个微小的内存监测工具,入口是 ActivityThread 的 attach 函数,Android 应用进程启动后,都会调用该函数:
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
...
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
// 如果已经可用的内存不足 1/4 着手处理杀死 Activity,并且这个时候,没有缓存进程
if (dalvikUsed > ((3*dalvikMax)/)) {
mSomeActivitiesChanged = ;
{
mgr.releaseSomeActivities(mAppThread);
} (RemoteException e) {
...
}
});
}
}


