Android is an operating system based on the Linux kernel and is aimed at mobile terminals. To meet its special needs as a mobile platform operating system, Google has specially designed and optimized it to enable applications to close but not exit, and the operating system to recycle and manage processes. This article analyzes the process resource recycling mechanism of the Android operating system at the two levels of Application Framework and Linux kernel with processes as granularity. Readers can gain a further understanding of the survival cycle of Android applications from this article, so as to build applications more rationally and efficiently.
Memory recycling in Android operating system can be divided into two levels:
1. Default memory recycling, that is, the default recycling of the Application Framework layer.
2. Kernel-level memory recycling.
Memory recovery in Linux kernel lowmemorykiller, OOM_killer.
Default memory recycling: (code can be found in class) Recycling action entry activityIdleInternal().
The trigger points for memory recycling in Android system can be roughly divided into three situations.
First, the user program calls StartActivity() to make the currently active Activity overwrite;
Second, the user presses the back key to exit the current application; third, start a new application.
The function interface that ultimately calls these events that trigger memory recovery is activityIdleInternal(). ActivityIdleInternal() will be called when ActivityManagerService receives the asynchronous message IDLE_TIMEOUT_MSG or IDLE_NOW_MSG. IDLE_NOW_MSG is caused by events such as the switching of the Activity and the change of the Activiy focus. IDLE_TIMEOUT_MSG is caused when the Activity starts timeout. Generally, this timeout is set to 10s. If an Activity within 10s still fails to start successfully, an asynchronous message IDLE_TIMEOUT_MSG will be sent for resource recycling. The main task of activityIdleInternal() is to change the status information of the activity in the system and add it to the list of different states. Its main work is as follows:
First, call scheduleAppGcsLocked() method to notify all tasks in progress for garbage collection. scheduleAppGcsLocked() will schedule the JVM's garbage collect to recycle part of the memory space. Here, it is just to notify each process to check the garbage and schedule the recycling time by itself, rather than synchronous recycling.
Then, remove all contents from the mStoppingActivities and mFinishigActivities lists, which are temporarily present in the temporary variable. These two lists store activity objects with current status stop and finish. For the stop list, if the finish status of the activity is true, determine whether it is necessary to stop immediately. If it is necessary to stop immediately, call destroyActivityLocked() to notify the target process to call the onDestroy() method. Otherwise, call resumeTopActivity() first to run the next Activity. If the finish status is false, stopActivityLocked() is called to notify the client process to stop the Activity. This situation generally occurs after the call to startActivity(). For the finish list, call destroyActivityLocked() directly to notify the client process to destroy the target Activity. Functions such as destroyActivityLocked here do not really change the use of memory, but just change their state to "allowed recycling". The real recycling is in the trimApplications() function to be called below.
private final void trimApplications() { synchronized (this) { // First remove any unused application processes whose package // has been removed. for (i=()-1; i>=0; i--) { (1)//kill process; } if (!updateOomAdjLocked()) { (2)//do something default } // Finally, if there are too many activities now running, try to // finish as many as we can to get back down to the limit. (3)do something } }
(1) After the program executes to trimApplications(), first check the process in the mRemovedProcesses list. The mRemovedProcesses list mainly contains crash processes, processes that did not respond within 5 seconds and were selected by the user to force close, and application development calls killBackgroundProcess to kill. Call Kill all such processes.
(2) Call the updateOomAdjLocked() function. If it returns successfully, it means that the Linux kernel supports the setOomAdj() interface. UpdateOomAdjLocked will modify the value of adj and notify the linux kernel. The kernel dynamically manages process resources (lowmemorykiller and oom_killer) based on the adj value and memory usage. If updateOomAdjLocked() returns false, it means that the current system does not support the setOomAdj() interface, and the default resource recycling will be performed locally.
(3) Finally, if too many activities are still running, recycle the excess activities. Most of the code of trimApplications() deals with default resource recycling in the absence of Oom_killer. The default recycling process (i.e. where the mark (2) in the code) is further analyzed below. The recycling process can be roughly described as follows.
Step 1: Get all currently running processes mLruProcesses. The sorting rules in mLruProcesses are based on the most recent use time. Count processes that cannot be closed in mLruProcesses. These processes that cannot be closed include processes that run service, processes that run broadcast receiver, etc.
Step 2: Set the current maximum number of running processes curMaxProcs = curMaxProcs + numServiceProcs (that is, the sum of the default maximum number of processes and the number of processes running Service). If the number of current processes () is greater than this value, iterates over all currently running processes, kill those processes that meet the conditions and free up memory. The condition for a process to be killed is that it must be a non-persistent process, that is, a non-system process, and must be an empty process, that is, there is no activity in the process. If you kill a process with an Activity, it is possible to close the program that the user is using, or make the application recovery delay increase, which affects the user experience; there must be no broadcast receiver. Running broadcast receiver is usually waiting for an event to occur. The user does not want such programs to be forced to be closed by the system; the number of services in the process must be 0. A process with a service is likely to provide some kind of service to one or more programs, such as GPS location services. Killing such processes will prevent other processes from serving properly.
Step 3: Check the currently running process again. If () is still greater than curMaxProcs, relax the conditions and recycle it again.
Step 4: The above three processes are all resource recycling for the entire process. After the above process is completed, the resource of the Activity will be recycled on a smaller granularity. Similar to the above, the list mLRUActivities stores all currently running activities, and the collation is also the least access principle. () Returns the number of activities running in the system, when it is greater than MAX_ACTIVITIES (MAX_ACTIVITIES is a constant, with a general value of 20, representing the maximum allowed simultaneous activity in the system). Partially satisfying the conditions will be recycled to reduce memory usage. All that is recycled here is the Activity memory resource, which will not kill the process or affect the operation of the process. When a process needs to call the killed Activity, it can reply from the saved state, which may require a relatively long delay.
Memory recovery in Linux kernel
lowmemorykiller
A function called updateOomAdjLocked() will be executed in the trimApplications() function. If false is returned, the default recycling will be performed. If true is returned, the default memory recycling will not be performed.
updateOomAdjLocked will update a variable named adj for each process and inform the Linux kernel. The kernel maintains a data structure containing adj (i.e., process table), and checks the system memory usage through lowmemorykiller, kills some processes and frees up memory when there is insufficient memory.
Since all applications in the Android operating system run in a separate Dalvik virtual machine environment, the Linux kernel cannot know the running status of each process, and cannot maintain an appropriate adj value for each process. Therefore, a set of mechanisms must be provided in the Android Application Framework to dynamically update the adj of each process. This is updateOomAdjLocked().
Android stipulates the default default based on the components running in the process and their status.Five recycling priorities:
IMPORTANCE_FOREGROUND:
IMPORTANCE_VISIBLE:
IMPORTANCE_SERVICE:
IMPORTANCE_BACKGROUND:
IMPORTANCE_EMPTY: