Dalvik heap memory management and recovery
The Heap used by the Dalvik Virtual Machine to allocate objects is divided into two parts: Active Heap and Zygote Heap. The following describes how to allocate these two parts and manage the heap memory based on the management mechanism.
Let's start with the Android system.
After the Android system is started, a Zygote process will create the first Dalvik virtual machine, which maintains only one heap. All application processes started later are fork by the Zygote process, and they all hold their own Dalvik virtual machines. During application creation, the Dalvik virtual machine uses the COW policy to copy the address space of the Zygote process.
COW policy: At the beginning (when the address space of the Zygote process is not copied), the application process and the Zygote process share the same heap used to allocate objects. When the Zygote process or application process writes to the heap, the kernel will execute the true copy operation, so that the Zygote process and application process have their own copy, this is the so-called COW. Because copy is very time-consuming, you must avoid copying or minimize the number of copies.
For this purpose, when the first application process is created, the used heap memory is divided into one part, and the unused heap memory is divided into another part. The former is called the Zygote heap, and the latter is called the Active heap. In this way, you only need to copy the content in the zygote heap to the application process. In the future, whether it is a Zygote process or an application process, when they need to allocate objects, they will be carried out on the Active heap. In this way, the Zygote heap can be executed with as few write operations as possible, thus reducing the copy operation during write operations. The objects allocated in the Zygote heap are mainly classes, resources, and objects pre-loaded by the Zygote process during startup. This means that these pre-loaded classes, resources, and objects can be shared for a long time in the Zygote process and application process. This reduces the copy operation and memory requirements.
Similar to JVM, The Dalvik virtual machine is also responsible for managing objects in the heap memory. It uses the tag clearing algorithm, but the details are slightly different.
The Mark-Sweep algorithm has two phases:
Mark stage: uses recursive object references to Mark referenced objects starting from the object's root set.
Sweep stage: reclaim memory occupied by unlabeled objects.
The Dalvik virtual machine uses Heap Bitmap to mark whether the object has been referenced. The so-called Heap Bitmap is an unsigned long array. If an object is referenced, the corresponding bit in Bitmap will be set to 1. Otherwise, it is set to 0. Dalvik uses two bitmaps to describe heap objects. One is called Live Bitmap and the other is called Mark Bitmap. Live Bitmap is used to Mark objects referenced during the last GC, that is, objects not recycled, and Mark Bitmap is used to Mark objects referenced by the current GC. In this way, you only need to reclaim the last referenced object.
In The Mark stage of garbage collection, all threads except The garbage collection thread must Stop The World. Otherwise, if The object references other objects during The GC process, it may lead to the failure to correctly mark every object. However, this will cause program freezing and lower efficiency. Therefore, the garbage collection thread and other threads must be allowed to execute Concurrent GC concurrently in the Mark stage ).
To achieve this, Dalvik divides the Mark stage into two steps:
The first step is to only mark the root SET object, that is, the objects referenced by global variables, stack variables, and register objects at the beginning of the GC process. This stage only allows GC threads to run, preventing these root SET objects from referencing other objects in this process.
Step 2: Use the reference relationships of these root SET objects to locate and Mark other objects in use. This stage allows concurrent execution of other threads and GC threads. In order to realize the concurrency between GC threads and other threads, You need to record the changes made by other threads to the object. The data structure that records these changes is called a Card Table.
When the Dalvik virtual machine collects part of the garbage, it actually only collects the objects allocated on the Active stack. Therefore, for the Dalvik virtual machine, the Card Table is used to record the reference of the objects allocated on the Zygote stack during the execution of the local garbage collection.
Unlike Bitmap, the size of each Card in the card Table is one byte. If the object corresponding to the Card is not modified in the second step, the value is clean; otherwise, the value is dirty. For modified objects, you need to re-mark these objects with GC threads after step 2. Because these objects are not many, this process is very fast, which is also the reason for two steps.
This article permanently updates the link address: