Android 操作系统中的内存回收


Android 系统中内存回收的触发点大致可分为三种情况:

第一种情况 用户程序调用 StartActivity(), 使当前活动的 Activity 被覆盖

第二种情况 :按下Back键,会调用finishActivityLocked,然后把Activity的finishing标志设为true,然后再调用startPausingLocked,当目标actiity完成暂停后,就会通知Ams,此时Ams从completePaused开始执行,由于此时暂停的Activity的finising状态已经变为true,所以会执行finishingActivtyLocked。

第三种情况 启动一个新的应用程序 。向Ams发送一个Idle消息,这会导致Ams开始执行activityIdleInternal方法,该方法首先处理mStoppingActivities中的对象,接着处理mFinishingActivities列表,然后再调用trimApplications
这些能够触发内存回收的事件最终调用的函数接口就是 activityIdleInternalLocked().

1.当 ActivityManagerService 接收到异步消息 DLE_NOW_MSG 时 将会被调用。
2.当 ActivityManagerService 接收到异步消息 IDLE_TIMEOUT_MSG 时将会被调用。
3.ActivityManagerService.的activityIdle中将会被调用
一,
1.IDLE_NOW_MSG 由 Activity 的切换以及 Activiy 焦点的改变等事件引发.
2.IDLE_TIMEOUT_MSG 在 Activity 启动超时的情况下引发,一般这个超时时间设为 10s,如果 10s 之内一个 Activity 依然没有成功启动,那么将发送异步消息 IDLE_TIMEOUT_MSG 进行资源回收。
文件路径:
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

private final class ActivityStackSupervisorHandler extends Handler {
。。。。。。。。。
void activityIdleInternal(ActivityRecord r) {
synchronized (mService) {
activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
}
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
.......
case IDLE_TIMEOUT_MSG: {
if (DEBUG_IDLE) Slog.d(TAG_IDLE,
"handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
if (mService.mDidDexOpt) {
mService.mDidDexOpt = false;
Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
nmsg.obj = msg.obj;
mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
return;
}
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
activityIdleInternal((ActivityRecord)msg.obj);
} break;
case IDLE_NOW_MSG: {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
activityIdleInternal((ActivityRecord)msg.obj);
} break;
}
}


3.activityIdle是在handleResumeActivity添加一个空闲任务,然后在looper线程空闲的时候调用
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && (mProfileFd != null)) {
try {
mProfileFd.close();
} catch (IOException e) {
}
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
主要就是检测当前activity栈是否为空,如果栈中有activity,那么就调用ActivityStactSupervisor. activityIdleInternalLocked方法

Z:\HLOS\frameworks\base\core\java\android\app\ActivityThread.java
调用ActivityManagerService的activityIdle方法在ActivityThread的内部handler Idler中。
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
if (mBoundApplication != null && mProfiler.profileFd != null
&& mProfiler.autoStopProfiler) {
stopProfiling = true;
}
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManagerNative.getDefault();
ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
" finished=" +
(a.activity != null && a.activity.mFinished));
if (a.activity != null && !a.activity.mFinished) {
try {
am.activityIdle(a.token, a.createdConfig, stopProfiling);
a.createdConfig = null;
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
prev = a;
a = a.nextIdle;
prev.nextIdle = null;
} while (a != null);
}
if (stopProfiling) {
mProfiler.stopProfiling();
}
ensureJitEnabled();
return false;
}
}

这是Message队列的内部类闲置handler,这个queueIdle回调在消息队列中没有消息可以处理的空闲时期被调起,此前已经分析过了。
queueIdle()
return true ,表示保留,当queueIdle执行完毕之后,不会移除这个IdleHandler
return false ,表示这个IdleHandler不需要保留,也就是只需要执行一遍。

接着应该看 Looper.myQueue().addIdleHandler()什么时候把 Idler 添加进去的了

final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
..............

if (!r.onlyLocalRequest) {
r.nextIdle = mNewActivities;
mNewActivities = r;
if (localLOGV) Slog.v(
TAG, "Scheduling idle handler for " + r);
Looper.myQueue().addIdleHandler(new Idler());
}
r.onlyLocalRequest = false;

// Tell the activity manager we have resumed.
if (reallyResume) {
try {
ActivityManagerNative.getDefault().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}

} else {
// If an exception was thrown when trying to resume, then
// just end this activity.
try {
ActivityManagerNative.getDefault()
.finishActivity(token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}

也就是说,在activity执行resume方法之后,系统会在当前的线程中添加一个空闲任务。
这边需要科普一下,一般我们在调用了finish方法,或者是启动了一个新的应用或者是activity方法之后,当前的activity会处于后台,并且处于空闲,因此就会触发queueIdle的方法,从而触发AMS的activityIdle的方法。

二,
现在我们可以主要分析 activityIdleInternalLocked方法了
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
Configuration config) {
if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);

ArrayList<ActivityRecord> finishes = null;
ArrayList<UserState> startingUsers = null;
int NS = 0;
int NF = 0;
boolean booting = false;
boolean activityRemoved = false;

ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
+ Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
if (fromTimeout) {
reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
}

// This is a hack to semi-deal with a race condition
// in the client where it can be constructed with a
// newer configuration from when we asked it to launch.
// We'll update with whatever configuration it now says
// it used to launch.
if (config != null) {
r.configuration = config;
}

// We are now idle. If someone is waiting for a thumbnail from
// us, we can now deliver.
r.idle = true;

//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (isFocusedStack(r.task.stack) || fromTimeout) {
booting = checkFinishBootingLocked();
}
}
//1.通知所有需要内存回收的进程进行内存回收(这些进程都保存在mProgressToGc列表中)
if (allResumedActivitiesIdle()) {
if (r != null) {
mService.scheduleAppGcsLocked();
}

if (mLaunchingActivity.isHeld()) {
mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
if (VALIDATE_WAKE_LOCK_CALLER &&
Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
mLaunchingActivity.release();
}
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
2. 分别拿到所有要stop和finish的activity存放在stops和finishs容器中,然后将记录清空
// Atomically retrieve all of the other things to do.
// 获取已经暂停的activity列表
final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(true);
NS = stops != null ? stops.size() : 0;
if ((NF = mFinishingActivities.size()) > 0) {
// 获取已经触发了finish方法的列表
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}

if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}

// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.task.stack;
if (stack != null) {
//如果该被暂停的activity已经调用了finish方法,那么就调用栈的finish当前的activity的方法
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
} else {
// 否则调用栈的stopActivity方法
stack.stopActivityLocked(r);
}
}
}

// Finish any activities that are scheduled to do so but have been
// waiting for the next one to start.
// 遍历finish列表中的每一个activity,如果当前栈不为空,就去触发栈的destroyActivityLocked方法
for (int i = 0; i < NF; i++) {
r = finishes.get(i);
final ActivityStack stack = r.task.stack;
if (stack != null) {
activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
//并没有真正意义上改变内存的使用,只是将其状态改变为“允许回收”,真正的回收在下面即将调用的 trimApplications() 函数中
}
}

if (!booting) {
// Complete user switch
if (startingUsers != null) {
for (int i = 0; i < startingUsers.size(); i++) {
mService.mUserController.finishUserSwitch(startingUsers.get(i));
}
}
}

mService.trimApplications(); //真正开始杀进程回收
//dump();
//mWindowManager.dump();

if (activityRemoved) {
resumeFocusedStackTopActivityLocked(); //删除成功后恢复焦点堆栈activity的显示
}

return r;
}



一、 scheduleAppGcsLocked()分析//通知各进程要GC
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

/**
* Schedule the execution of all pending app GCs.
*/
final void scheduleAppGcsLocked() {
mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG);
//从mProcessesToGc列表中取出下一个ProcessRecord ,并发送一个延迟消息,由performAppGcsIfAppropriateLocked()来执行
if (mProcessesToGc.size() > 0) {
// Schedule a GC for the time to the next process.
ProcessRecord proc = mProcessesToGc.get(0);
Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);

long when = proc.lastRequestedGc + GC_MIN_INTERVAL;
long now = SystemClock.uptimeMillis();
if (when < (now+GC_TIMEOUT)) {
when = now + GC_TIMEOUT;
}
mHandler.sendMessageAtTime(msg, when);
}
}
final class MainHandler extends Handler {
......
case GC_BACKGROUND_PROCESSES_MSG: {
synchronized (ActivityManagerService.this) {
performAppGcsIfAppropriateLocked();
}
} break;
......
}

/**
* If all looks good, perform GCs on all processes waiting for them.
*/
final void performAppGcsIfAppropriateLocked() {
if ( canGcNowLocked()) {
performAppGcsLocked();
return;
}
// Still not idle, wait some more.
scheduleAppGcsLocked();
}

/**
* Returns true if things are idle enough to perform GCs.
*/
//判断是否足够闲置可以来执行GC
private final boolean canGcNowLocked() {
boolean processingBroadcasts = false;
for (BroadcastQueue q : mBroadcastQueues) {
if (q.mParallelBroadcasts.size() != 0 || q.mOrderedBroadcasts.size() != 0) {
processingBroadcasts = true;
}
}
return !processingBroadcasts
&& (isSleepingLocked() || mStackSupervisor. allResumedActivitiesIdle());
}

Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
boolean allResumedActivitiesIdle() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack) || stack.numActivities() == 0) {
continue;
}
final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity == null || !resumedActivity.idle) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ stack.mStackId + " " + resumedActivity + " not idle");
return false;
}
}
}
// Send launch end powerhint when idle
mService.mActivityStarter.sendPowerHintForLaunchEndIfNeeded();
return true;
}
/**
* Perform GCs on all processes that are waiting for it, but only
* if things are idle.
*/
final void performAppGcsLocked() {
final int N = mProcessesToGc.size();
if (N <= 0) {
return;
}
if ( canGcNowLocked()) {
while (mProcessesToGc.size() > 0) {
ProcessRecord proc = mProcessesToGc.remove(0); //在mProcessesToGc列表中逐个取出每个需要进行gc的ProcessRecord对象,同时移除
if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) {
if ((proc.lastRequestedGc+GC_MIN_INTERVAL)
<= SystemClock.uptimeMillis()) {

// To avoid spamming the system, we will GC processes one
// at a time, waiting a few seconds between each.
//如果超过了最小时间间隔,则从mProcessesToGc列表中取出下一个app,并发送一个延迟消息
performAppGcLocked(proc);
scheduleAppGcsLocked();
return;
} else {
// It hasn't been long enough since we last GCed this
// process... put it in the list to wait for its time.
//先检查app上一次进行gc的时间,并和当前时间进行对比,如果还没超过最小间隔,则将指定的app 加入到mProcessesToGc列表中
addProcessToGcListLocked(proc);
break;
}
}
}

scheduleAppGcsLocked();
}
}
/**
* Ask a given process to GC right now.
*/
final void performAppGcLocked(ProcessRecord app) {
try {
app.lastRequestedGc = SystemClock.uptimeMillis();
if (app.thread != null) {
if (app.reportLowMemory) {
app.reportLowMemory = false;
app.thread.scheduleLowMemory();
} else {
app.thread.processInBackground();
}
}
} catch (Exception e) {
// whatever.
}
}

Z:\HLOS\frameworks\base\core\java\android\app\ActivityThread.java
@Override
public void scheduleLowMemory() {
sendMessage(H.LOW_MEMORY, null);
}
public void processInBackground() {
mH.removeMessages(H.GC_WHEN_IDLE);
mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
}
private class H extends Handler {
......
case LOW_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
handleLowMemory();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case GC_WHEN_IDLE:
scheduleGcIdler();
break;
.......
}

final void handleLowMemory() {
ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);

final int N = callbacks.size();
for (int i=0; i<N; i++) {
callbacks.get(i).onLowMemory(); //回调该进程所包含的所有组件的onLowMemory方法
}
// Ask SQLite to free up as much memory as it can, mostly from its page caches.
if (Process.myUid() != Process.SYSTEM_UID) {
int sqliteReleased = SQLiteDatabase.releaseMemory(); / /不是SYSTEM_UID就释放SQLite模块占用的内存。
EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
}
// Ask graphics to free up as much as possible (font/image caches)
Canvas.freeCaches(); //释放应用中所有的canvas对象
// Ask text layout engine to free also as much as possible
Canvas.freeTextLayoutCaches();/ /释放应用中所有的Text Layout
BinderInternal.forceGc("mem"); //释放该进程的Binder对象
}

void scheduleGcIdler() {
if (!mGcIdlerScheduled) {
mGcIdlerScheduled = true;
Looper.myQueue().addIdleHandler(mGcIdler); //正常GC都是任务空闲时执行
}
mH.removeMessages(H.GC_WHEN_IDLE);
}
final class GcIdler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
doGcIfNeeded();
return false;
}
}
MIN_TIME_BETWEEN_GCS = 5*1000;
void doGcIfNeeded() {
mGcIdlerScheduled = false;
final long now = SystemClock.uptimeMillis();
//Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
// + "m now=" + now);
if ((BinderInternal.getLastGcTime()+ MIN_TIME_BETWEEN_GCS) < now) {
//两次GC间隔不能小于5S
//Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
BinderInternal.forceGc("bg"); //释放该进程的Binder对象
}
}

Z:\HLOS\frameworks\base\core\java\com\android\internal\os\BinderInternal.java
public static void forceGc(String reason) {
EventLog.writeEvent(2741, reason);
VMRuntime.getRuntime().requestConcurrentGC(); //虚拟机GC
}

二、 trimApplications()分析 //真正回收内存
final void trimApplications() {
synchronized (this) {
int i;

// First remove any unused application processes whose package
// has been removed.
for (i=mRemovedProcesses.size()-1; i>=0; i--) {
final ProcessRecord app = mRemovedProcesses.get(i);
//1.必须是空进程,即进程中没有任何 activity 存在。如果杀死存在 Activity 的进程,有可能关闭用户正在使用的程序,或者使应用程序恢复的时延变大,从而影响用户体验;
//2.必须无 broadcast receiver。运行 broadcast receiver 一般都在等待一个事件的发生,用户并不希望此类程序被系统强制关闭;
//3.进程中 service 的数量必须为 0。存在 service 的进程很有可能在为一个或者多个程序提供某种服务,如 GPS 定位服务。杀死此类进程将使其他进程无法正常服务
if (app.activities.size() == 0
&& app.curReceiver == null && app.services.size() == 0) {
Slog.i(
TAG, "Exiting empty application process "
+ app.toShortString() + " ("
+ (app.thread != null ? app.thread.asBinder() : null)
+ ")\n");
if (app.pid > 0 && app.pid != MY_PID) {
app.kill("empty", false);
} else {
try {
app.thread.scheduleExit(); //pid为0说明已经杀过了,pid==MY_PID说明是当前system进程
} catch (Exception e) {
// Ignore exceptions.
}
}
cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/);
mRemovedProcesses.remove(i);

if (app.persistent) {
addAppLocked(app.info, false, null /* ABI override */);
}
}
}

// Now update the oom adj for all processes.
updateOomAdjLocked();
}
}
Z:\HLOS\frameworks\base\core\java\android\app\ActivityThread.java
public final void scheduleExit() {
sendMessage(H.EXIT_APPLICATION, null);
}
private class H extends Handler {
......
case EXIT_APPLICATION:
if (mInitialApplication != null) {
mInitialApplication.onTerminate(); //This method is for use in emulated process environments
}
Looper.myLooper().quit(); / /退出
break;
......
}
Z:\HLOS\frameworks\base\services\core\java\com\android\server\am\ProcessRecord.java

void kill(String reason, boolean noisy) {
if (!killedByAm) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
if (noisy) {
Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason);
}
if(toShortString().contains("com.android.dialer")||toShortString().contains("com.android.server.telecom")){
Slog.i(TAG, "Killing return leihujun dialer");
return;
}
EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
Process.killProcessQuiet(pid);
ActivityManagerService.killProcessGroup(uid, pid);
if (!persistent) {
killed = true;
killedByAm = true;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}


1.mRemovedProcesses 列表中主要包含了 crash 的进程、5 秒内没有响应并被用户选在强制关闭的进程、以及应用开发这调用 killBackgroundProcess 想要杀死的进程。调用 Process.killProcess 将所有此类进程全部杀死

















  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android内存管理是操作系统的关键部分,它可以确保系统资源的高效利用和最佳性能。下面是一些常见的内存管理技术。 1、进程和线程管理:Android使用进程和线程来执行应用程序。每个应用程序都有一个主线程和多个其他线程来执行不同的任务。操作系统管理这些进程和线程,通过调度和优先级管理来确保系统资源的最佳使用。 2、内存映射和虚拟内存Android使用内存映射和虚拟内存技术来管理内存内存映射是一种将文件或设备映射到内存的技术,这样可以快速访问数据。虚拟内存是一种将虚拟地址映射到物理内存的技术,这样可以大大增加可用内存的数量。 3、内存回收和垃圾回收Android使用内存回收和垃圾回收技术来管理内存内存回收是一种将不再使用的内存分配回操作系统的技术,这样可以确保系统资源的最佳利用。垃圾回收是一种自动回收不再使用的对象和内存的技术,这样可以避免内存泄漏和内存溢出。 4、内存压缩和交换:Android使用内存压缩和交换技术来管理内存内存压缩是一种将不常用的内存压缩成更小的空间的技术,这样可以释放更多的内存。交换是一种将内存数据交换到硬盘上的技术,这样可以释放更多的内存空间。 总之,Android内存管理是一个复杂的过程,需要使用多种技术来确保系统资源的高效利用和最佳性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值