Reading notes, if necessary, please indicate the author: Yuloran (t.cn/EGU6c76)

preface

This article is divided into two parts, the first part is the translation of Garbage Collection in Android, and the second part introduces the differences between Android virtual machines and Java virtual machines.

Garbage Collection in Android

Speaker Introduction

Colt McAnlis is a developer at Google. To facilitate writing, the author will summarize the content of the video from a first-person perspective.

Automatic memory management trap

Many high-performance languages, such as C and C++, require developers to manually manage the allocation and release of memory, but it is easy to forget to release allocated memory when the code is large and the business logic is complex, resulting in memory leaks. The automatic garbage collection mechanism for Dalvik (< Android 5.0) or ART (≥ Android 5.0) virtual machines located at Android Runtime improves productivity by freeing developers from the need to manually manage memory. But it also hides performance traps, where the most important concern is how memory is allocated and used.

Origin of GC concept

The automatic memory management mechanism, called Garbage Collection, was introduced by John McCarthy in 1959 to solve problems in LISP. It mainly involves two principles:

  1. Find objects that are no longer accessible;
  2. Reclaim the resources occupied by these objects.

Difficulties in GC implementation

Imagine that you have 20,000 objects allocated. How do you identify which objects are no longer accessible, or when GC events should be triggered?

This is so hard! Fortunately, in the 50 years since the GC concept was first introduced, we have been working on improving the performance of the garbage collector, which is why the Android garbage collector is much more complex than John McCarthy suggested.

Android GC profile

In fact, the Android system divides the memory used by the process into multiple Spaces based on the type of objects allocated and how the system manages those objects during GC. The space where the newly allocated objects are located depends on your Android Runtime version. Up to 5.0 is the ART (Android Runtime) virtual machine and up to 5.0 is the Dalvik virtual machine.

Author’s note: See the difference analysis below for the specific meaning of the above figure.

Each space has a Set Size, and the system keeps track of how much memory the entire program takes up. When the program occupies a certain amount of memory, the system triggers a GC event to reclaim memory for future allocation to other objects:

GC events also behave differently in the Dalvik virtual machine and the ART virtual machine. In the Dalvik virtual machine, many GC events are “Stop the World Event” :

The ART virtual machine extends the parallel GC algorithm to eliminate large GC pauses, but there are still short pauses for important steps:

Frame drop caused by GC

Although systems engineers have done a lot of optimizations to increase GC speed and reduce lag, your App may still have performance issues. As we know, Android renders a frame every 16 ms, so the longer the GC is in a frame, the less time is left for the business logic:

If your GC is too frequent (such as creating a large number of temporary objects in a loop) or takes too long to GC, this will result in a frame processing time exceeding the 16 ms limit, which will cause the user to stutter and drop frames:

Memory analysis tool

Fortunately, Android Studio’s Profiler tool can be used to view memory usage and allocation.

conclusion

However, memory tuning is easier said than done, so you should also watch the following video to learn more about performance tuning:

link

Differences between Android VMS and Java VMS

In fact, I mainly want to pay attention to the differences in memory layout and GC algorithm of these virtual machines. As for the executable file formats (.jar,.dex,.elf) and bytecode structures (class, dex, ELF) corresponding to JVM, Dalvik, and ART, they are obviously different. However, there is little information about the memory layout of Android VIRTUAL machines on the Internet. Most of the information only focuses on the allocation of runtime heap memory and its GC algorithm, and there is no reference to the virtual machine stack (method execution model), constant pool, method area, so this part cannot be compared with Java virtual machines. However, there is a universal connection between everything, nothing can be created in a vacuum. Since the method execution model of Java virtual machine is conceptually similar to that of C language, Dalvik and ART can also be understood in this way, and the details are definitely different, after all, the instruction set is different. Really want to investigate, can only see the virtual machine source.

I’ve got a headache. Take a look at this graph:

This figure describes the space division of Dalvik and ART virtual machines to the runtime heap, which has corresponding implementation in the source code. For details, please refer to:

  • Dalvik VIRTUAL Machine garbage collection mechanism brief introduction and learning plan – Shengyang Luo
  • ART Run-time garbage collection mechanism brief introduction and learning plan – Shengyang Luo

Or use the cloud to read more conveniently.

Basically, instead of using the generational collection algorithm used by the HotSpot VIRTUAL machine, the Android virtual machine uses either mark-clean or mark-copy algorithms, which can be specified at compile time. See Android Garbage Collection/ Dalvik GC, but it’s usually a tag cleaning algorithm.

The following is an excerpt from The Dalvik VIRTUAL Machine for Android Virtual Machines:

  • Memory management

    ◇ The size of the Java Object Heap is limited, for example, 16M/24M/32M/48M. ◇ Bitmap Memory(External Memroy) : The size is included in the Java Object Heap

  • Garbage Collection (GC)

    Mark: Marks objects with RootSet. Sweep: reclaims objects that are not referenced

  • Before GingerBread (Android 2.3)

    Stop-the-word: when a garbage collection thread is executing, all other threads Stop. Full heap collection: when a garbage collection is complete at one time, the program stops for more than 100ms

  • After GingerBread (Android 2.3)

    ◇ Cocurrent: In most cases, the garbage collection thread executes concurrently with other threads. ◇ Partial collection may only be collected at a time

The ART virtual machine extends the parallel GC by dividing the heap memory into more different types of concrete Spaces and using different GC algorithms for shorter GC pause times.

Dalvik virtual machine

wiki

Dalvik VIRTUAL machine is one of the core components of Android mobile device platform jointly developed by Google and other manufacturers. It supports the running of Java applications that have been converted to the.dex (i.e. “Dalvik Executable”) format. Dex format is a compression format specially designed for Dalvik, suitable for systems with limited memory and processor speed. Written by Dan Bornstein, Dalvik takes its name from the small fishing village of Dalvik, located in Eyjafjor ður, where his ancestors once lived.

While most virtual machines, including the JVM, are a stack machine, the Dalvik vm is a register machine. Both architectures have their advantages and disadvantages. In general, stack-based machines require more instructions, while register-based machines require longer instructions.

Since Android version 5.0, Android Runtime (ART) has replaced Dalvik as the default virtual machine in the system.

Differences:

  • The Dalvik VIRTUAL machine did not use just-in-time compilation (JIT) technology in its early days. Starting with Android 2.2, the Dalvik virtual machine also supports JIT.
  • The Dalvik virtual machine has its own bytecode and does not use Java bytecode.
  • Dalvik is register-based, while the JVM is stack-based.
  • The Dalvik VM preloads categories through Zygote, which performs the initialization of the virtual machine, which is also different from the JVM.

Mark-sweep Algorithm

The Dalvik VIRTUAL machine uses the Mark-sweep algorithm without Compact, so it is simpler than the Java virtual machine.

(a) State before GC. The example has a GC Root where all objects are unmarked.

(b) State after GC marking. In the tagging phase, all Active Objects are tagged.

(c) State after GC cleaning. All garbage has been collected, and the mark status of all live objects has been reset to false.

GC trigger time

  • When OOM is about to be generated
  • Maximum heap memory usage (system available)
  • Display calls to GC ()

The GC log

In Dalvik (not ART), each garbage collection prints the following information to logCAT:

D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>
Copy the code

Example:

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
Copy the code

Reasons for garbage collection

What triggers garbage collection and what kind of collection. Possible causes include:

  • GC_CONCURRENT: Concurrent garbage collection that frees up memory when your heap starts to occupy it.
  • GC_FOR_MALLOC: Garbage collection caused when your application tries to allocate memory when the heap is full and the system has to stop your application and reclaim memory.
  • GC_HPROF_DUMP_HEAP: Garbage collection that occurs when you request to create a HPROF file to analyze the heap.
  • GC_EXPLICIT: Explicit garbage collection, such as when you call GC () (you should avoid the call and trust the garbage collection to run as needed).
  • GC_EXTERNAL_ALLOC: This only applies to API level 10 and below (newer versions will allocate any memory in the Dalvik heap). Garbage collection of externally allocated memory (such as pixel data stored in native memory or NIO byte buffers).

To release a quantity to

The amount of memory recovered from this garbage collection.

Heap statistics

The percentage of free heap space is equal to (number of live objects)/(total heap size).

External memory statistics

API level 10 and lower externally allocated memory (amount of allocated memory)/(limit at which reclamation occurs).

The pause time

The larger the heap, the longer the pause time. Concurrent pause times show two pauses: one at the beginning of the collection and one near the completion of the collection. As these log messages accumulate, notice the increase in heap statistics (3571K/9991K values in the example above). If this value continues to increase, a memory leak may occur.

The ART of the virtual machine

wiki

Android Runtime (ART for short) is a running environment for the Android operating system. It was developed by Google and released in 2013 as a test feature in Android 4.4. Replaced the Dalvik VIRTUAL Machine as a formal runtime library in Android 5.0 and later. ART, which converts an application’s bytecode to machine code, is a new kind of virtual machine for Android. The main difference between it and Dalvik is that Dalvik adopts JIT technology, while ART adopts Ahead-of-time (AOT) technology. ART also improves performance, Garbage Collection, application errors, and performance analysis.

JIT was first introduced into Dalvik VM in Android 2.2 system. When the application is started, JIT optimizes the execution of the program code through continuous performance analysis. During the process of program running, Dalvik VM continuously compiles bytecode into machine code. Unlike the Dalvik VIRTUAL machine, ART introduces AOT, a precompilation technique that recompiles all bytecode into machine code during application installation. There is no need to compile the application in real time, just make direct calls. Therefore, ART greatly improves the running efficiency of application programs, reduces the power consumption of mobile phones, improves the battery life of mobile devices, and also greatly improves the garbage collection mechanism. To ensure backward compatibility, ART uses the same Dalvik bytecode files (dex), that is, the dex files are kept in the application directory for older programs to call while.odex files are replaced with executable and linkable Format (ELF) executables. Once a program is compiled by the ART dex2OAT command, the program will be run through the ELF executable. Therefore, compared with Dalvik VIRTUAL machine mode, the installation of Android applications in ART mode takes more time and occupies more storage space (i.e. internal storage for the compiled code), but saves a lot of time for real-time compilation in Dalvik Virtual machine.

The ART mode introduced by Google in Android 4.4 is only a preview version of ART, and the system still uses Dalvik VIRTUAL machine by default. 4.4 The ART preview provided above is quite different from the ART runtime library after Android 5.0, especially in terms of compatibility.

The GC log

Unlike Dalvik, ART does not log messages for garbage collection that is not explicitly requested. Garbage collection is printed only if it is considered slow. More specifically, only when the garbage collection pause exceeds 5ms or the garbage collection duration exceeds 100ms. If the application is not in a perceptible paused process state, its garbage collection is not considered slow. Explicit garbage collection is always logged.

ART will include the following information in its garbage collection log message:

I/art: <GC_Reason> <GC_Name> <Objects_freed>(<Size_freed>) AllocSpace Objects, <Large_objects_freed>(<Large_object_size_freed>) <Heap_stats> LOS objects, <Pause_time(s)>
Copy the code

Example:

I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects, 21(416KB) LOS objects, 33% free, 25MB/38MB, Paused 1.230 ms total 67.216 msCopy the code

Reasons for garbage collection

What triggers garbage collection and what kind of collection. Possible causes include:

  • Concurrent: Concurrent garbage collection that does not suspend application threads. This garbage collection runs in a background thread and does not block allocation.
  • Alloc: Garbage collection caused by your application trying to allocate memory when the heap is full. In this case, garbage collection occurs in the allocation thread.
  • Explicit: Garbage collection explicitly requested by the application, for example, by calling GC () or GC (). As with Dalvik, the best practice in ART is that you should trust garbage collection and avoid requesting explicit garbage collection if possible. Explicit garbage collections are not recommended because they prevent allocation threads from unnecessarily wasting CPU cycles. If explicit garbage collection causes other threads to be preempted, they can also cause stalling (interruption, jitter, or pause in the application).
  • NativeAlloc: Reclamation caused by native allocation (such as bitmap or RenderScript allocation of objects) resulting from native memory stress.
  • CollectorTransition: collection caused by heap conversion; This collection is caused by a run time switch garbage collection. The collector transformation involves copying all objects from the free list space to the collision pointer space (and vice versa). Currently, collector transitions occur only when the application changes the process state from a perceptible paused state to a perceptible non-paused state (and vice versa) on devices with small RAM.
  • HomogeneousSpaceCompact is free list space to free list space compression, which usually occurs when an application enters a perceptible pause in progress. The main reason for doing this is to reduce RAM usage and defragment the heap.
  • DisableMovingGc: it is not really a garbage collection, but please note that concurrent pile compression occurs, due to the use of the GetPrimitiveArrayCritical, recycling discouraged. In general, it is strongly recommended that do not use GetPrimitiveArrayCritical, because it has a limit in terms of moving collector.
  • HeapTrim: this is not a garbage collection reason, but please note that recycling is blocked until the HeapTrim is complete.

Garbage collection name

ART has a number of different garbage collections that can be run.

  • Concurrent Mark Sweep (CMS) : An entire heap collector that frees and recycles all Space other than the Image Space.
  • Concurrent partial mark sweep: Almost the entire heap collector, which reclaims all Space except the Image Space and Zygote Space.
  • Concurrent sticky mark sweep: Generates a collector that can only release objects allocated since the last garbage collection. This garbage collection runs more frequently than full or partial tag sweep because it is faster and has a shorter pause time.
  • Marksweep + Semispace: Non-concurrent, replication garbage collection for heap conversion and homogeneous space compression (defragmentation of the heap).

Released object

The number of objects collected from non-large object Spaces in this garbage collection.

Release size

The number of bytes collected from non-large object Spaces in this garbage collection.

Freed large objects

The number of objects collected from the large object space in this garbage collection.

The size of the large object to be freed

The number of bytes collected from the large object space in this garbage collection.

Heap statistics

Free percentage and (number of live objects)/(total heap size).

The pause time

Typically, the pause time is proportional to the number of object references modified at garbage collection runtime. Currently, ART CMS garbage collection is paused only once when the garbage collection is about to complete. Moving garbage collection pauses are long and persist for most garbage collections.

If you see a lot of garbage collection in LogCAT, notice the increase in heap statistics (25MB/38MB values in the example above). If this value continues to increase and does not continue to decrease, a memory leak may occur. Or, if you see a garbage collection with the cause “Alloc,” then you are nearing heap capacity and will soon have an OOM exception.

The attached

Official GC log text

There seems to be no English version of this website, but some Chinese explanations are awkward, such as “image space”. What the hell is this? Image Space…