Overview of android memory management mechanism

About the author: CSDN content partner and technical expert, built an APP with tens of millions of daily users from scratch.
Focus on sharing original series of articles in various fields, specializing in java backend, mobile development, artificial intelligence, etc. I hope everyone will support me.

Insert image description here

1. Introduction

We continue to summarize and learn basic knowledge , review the past and learn new things.

This article mainly describes memory management in Android and memory management related knowledge points in Java.

2. Overview

Android memory optimization is an important part of performance optimization, such as memory overflow (OOM). These are closely related to memory, so we need to master some relevant knowledge.

The Android Runtime (ART) and Dalvik virtual machine use paging and memory mapping to manage memory.
This means that any memory modified by the application, whether by allocating a new object or tapping a memory-mapped page, will always reside in RAM and cannot be swapped out.
To free memory from an application, you can only release object references held by the application, making the memory available for the garbage collector.
There is one exception to this: any unmodified memory-mapped file (such as code) can be swapped out of RAM if the system wants to use its memory elsewhere.

Android devices contain three different types of memory: RAM, zRAM, and storage.

Insert image description here

  • RAM is the fastest type of memory, but its size is usually limited.
  • zRAM is the RAM partition used for swap space. All data is compressed when placed into zRAM and then decompressed when copied out of zRAM. This portion of RAM grows or shrinks as pages are moved in and out of zRAM.
  • Storage contains all persistent data (such as file systems, etc.), as well as added object code for all applications, libraries, and platforms. The memory has a much larger capacity than the other two types of memory.

The memory to be requested is greater than the remaining memory allocated to the application by the system

3. Related concepts

3.1 Garbage collection

A managed memory environment such as ART or the Dalvik virtual machine keeps track of every memory allocation. Once it determines that the program is no longer using a piece of memory, it releases the memory back to the heap without any intervention from the programmer.
Garbage collection has two goals: one is to find data objects that will be inaccessible in the future, and the other is to reclaim the resources used by these objects.

We introduced in the previous article Jvm heap classification that the heap memory is divided into three parts: new generation, old generation, and permanent generation (metaspace).
The memory heap in Android is also divided into generations. Each generation of the heap has its own dedicated upper limit on the amount of memory that the corresponding object can occupy. Whenever a generation begins to fill up, the system performs a garbage collection event to free up memory.
The duration of a garbage collection depends on which generation of objects it collects and how many live objects there are in each generation.

Although garbage collection is very fast, it still affects the performance of your application. Normally, you have no control from your code about when a garbage collection event occurs. The system has a specific set of criteria for determining when to perform garbage collection.
When the conditions are met, the system stops the execution process and starts garbage collection. If garbage collection occurs during an intensive processing loop such as animation or music playback, it may increase processing time,
which may cause code execution in the application to exceed the recommended 16 millisecond threshold for efficient and smooth frame rendering.

3.2 Allocation and recycling of application memory

The Dalvik heap size per application can grow as needed, but cannot exceed the system-defined upper limit for each application. The exact heap size limit for different devices depends on the overall available RAM size of the device ,
we can check the available space through code

ActivityManager.getMemoryClass() 查询当前应用的Heap Size

Logical Heap Size is not equivalent to the actual physical memory size used. Proportional Set Size (PSS) records the memory occupied by the application itself and shared with other processes.
The Android system does not defragment the free memory area in the Heap. The system will only determine whether the remaining space at the end of the Heap is enough before new memory allocation. If there is not enough space, it will trigger a GC operation to free up more free memory space.

There is a large amount of shared memory in Android, such as Zygote process, static data, etc.

3.3 Switch applications

Android keeps non-foreground apps in the cache when the user switches between apps. Non-foreground applications refer to applications that users cannot see or do not run foreground services (such as music playback).
For example, when a user first launches an app, the system creates a process for it; but when the user leaves the app, the process does not exit. The system keeps the process in cache. If the user returns to the app later, the process is reused, making app switching faster.

If your app has a cached process that holds resources that are not currently needed, it can affect the overall performance of the system even when the user is not using your app. When system resources (such as memory) are insufficient,
it will terminate processes in the cache. The system also considers terminating the process taking up the most memory to free up RAM.

3.4 Out of memory management

Android has two main mechanisms for handling low-memory conditions: the kernel swap daemon and the low-memory termination daemon.

kernel swap daemon

The kernel swap daemon (kswapd) is part of the Linux kernel and is used to convert used memory into available memory. This daemon becomes active when there is insufficient memory available on the device. The Linux kernel has upper and lower thresholds for available memory.
When available memory drops below the lower threshold, kswapd begins reclaiming memory. When free memory reaches the upper threshold, kswapd stops reclaiming memory.

Low memory kill daemon

Many times, the kernel swap daemon (kswapd) fails to free up enough memory for the system. In this case, the system uses onTrimMemory() to notify the application that it is low on memory and should reduce its allocation.
If that's not enough, the kernel starts terminating processes to free up memory. It uses the low memory kill daemon (LMK) to do this.

LMK uses an "out of memory" score called oom_adj_score to prioritize running processes and determine which processes to terminate. The process with the highest score is killed first. Background applications are terminated first, and system processes are terminated last.

4. Actively manage application memory

RAM is a precious resource, and although both the Android Runtime (ART) and the Dalvik virtual machine perform garbage collection tasks regularly, this does not mean that the location and time of application allocation and release of memory can be ignored.
You still need to avoid introducing memory leaks (usually caused by retaining object references in static member variables) and release all Reference objects at the appropriate time (as defined by lifecycle callbacks).

There are two scenarios for OOM, one is real insufficient memory, and the other is insufficient available memory.

4.1 Memory monitoring

In order to make better use of memory, we need to monitor the memory ourselves. The main indicators of memory monitoring are: memory usage and OOM. We can check memory usage in many ways:

Check memory usage through command line

adb shell dumpsys meminfo -a com.xxx
Insert image description here

Via Android Studio’s Profiler tool

via code

For details, please refer to Memory Analyzer (MAT) to analyze the hprof file preparation in memory and obtain the memory file.

4.2 Release memory

There are many ways we can handle running out of system memory in our applications

ComponentCallbacks2 interface

Implement the ComponentCallbacks2 interface in the Activity class (or elsewhere), use the provided onTrimMemory() callback method, and then release the object

For example, you can implement the onTrimMemory() callback to respond to different memory-related events as follows:

import android.content.ComponentCallbacks2;
// Other import statements ...

public class MainActivity extends AppCompatActivity
    implements ComponentCallbacks2 {
    
    

    // Other activity code ...

    /**
     * Release memory when the UI becomes hidden or when system resources become low.
     * @param level the memory-related event that was raised.
     */
    public void onTrimMemory(int level) {
    
    

        // Determine which lifecycle or system event was raised.
        switch (level) {
    
    

            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:

                /*
                   Release any UI objects that currently hold memory.

                   The user interface has moved to the background.
                */

                break;

            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:

                /*
                   Release any memory that your app doesn't need to run.

                   The device is running low on memory while the app is running.
                   The event raised indicates the severity of the memory-related event.
                   If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system will
                   begin killing background processes.
                */

                break;

            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:

                /*
                   Release as much memory as the process can.

                   The app is on the LRU list and the system is running low on memory.
                   The event raised indicates where the app sits within the LRU list.
                   If the event is TRIM_MEMORY_COMPLETE, the process will be one of
                   the first to be terminated.
                */

                break;

            default:
                /*
                  Release any non-critical data structures.

                  The app received an unrecognized memory level value
                  from the system. Treat this as a generic low-memory message.
                */
                break;
        }
    }
}

Override onTrimMemory(), onLowMemory() and other methods in application

4.3 Check how much memory should be used

Query the system by calling getMemoryInfo(), which will provide information about the current memory status of the device, including available memory, total memory and memory threshold (if the memory usage reaches this value, the system will start to terminate the process).
The ActivityManager.MemoryInfo object also exposes a simple boolean value, lowMemory, which you can use to determine if the device is low on memory.


// Get a MemoryInfo object for the device's current memory status.
private ActivityManager.MemoryInfo getAvailableMemory() {
    
    
    ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);
    return memoryInfo;
}

4.4 Written at the back

java memory allocation and memory recycling algorithm

For Java's memory management, we need to clearly understand Java's memory allocation area and memory recycling algorithm, and
master several garbage collection algorithms and ideas, adaptation scenarios and optimization and evolution processes. Commonly used ones are:

Mark-and-sweep algorithm

  1. Mark all objects that need to be recycled
  2. Recycle all marked objects uniformly

To mark each area is relatively inefficient and will produce a large number of discontinuous fragments.

Replication algorithm

  1. Divide the entire memory into two equal-sized blocks, such as the left and right sides
  2. After one block of memory (for example, the left) is used up, copy the surviving objects to another block (for example, the right)
  3. Then clean up another piece of memory (such as the left) to make it continuous

This is a waste of memory because there is always an area that is empty and is ready for copying.

Mark-collation algorithm

  1. Mark each area and mark all objects that need to be recycled
  2. Move live objects together
  3. Clean up remaining objects to be recycled

Generational collection algorithm

  1. Combine multiple collection algorithms

The difference between android dalvik and art

Android is based on Java voice, but it still has its own unique transformation. Dalvik's garbage collection algorithm is fixed and will not change after the system is determined for each mobile phone,
while Art's garbage collection algorithm can be changed during operation. changing,

4.5 Related tools

Memory stress test

stressapptest
Stress application test (stressapptest) is a memory interface test that helps create realistic high-load scenarios to test the various memory and hardware limitations of the application.
With the ability to define time and memory limits, this test allows you to write instrumentation to verify which real-world situations result in high memory consumption.
For example, use the following set of commands to push a static library in the data file system, make it executable, and run a stress test at 990 MB for 20 seconds:

    adb push stressapptest /data/local/tmp/
    adb shell chmod 777 /data/local/tmp/stressapptest
    adb shell /data/local/tmp/stressapptest -s 20 -M 990

  

You can learn by yourself.

5. Recommended reading

Java column

SQL Column

Data Structures and Algorithms

Android learning column

ddd

Guess you like

Origin blog.csdn.net/fumeidonga/article/details/135207027