Android memory optimization details

Common memory problems

There are three common memory problems:

  • Memory jitter
  • Memory leaks
  • Out of memory

Memory jitter

Memory jitter

A large number of objects are created or reclaimed in a short period of time.

Cause memory jitter occurs

Mainly frequent (very important) in the loop to create objects (resulting in a large number of object is created in a short time, because of the new object is to take up memory space and is a frequent, if once or twice in a loop to create objects of memory, won’t cause serious memory jitter can accept is inevitable, so you memory jitter is frequent, The effect of memory jitter is that if jitter is very frequent, the garbage collection mechanism will run frequently (a large number of objects are generated in a short period of time, requiring a large amount of memory, and the jitter is frequent, the memory may need to be reclaimed for the creation of objects, and the garbage collection mechanism will naturally run frequently).

Impact of Memory jitter

Frequent memory jitter causes garbage collection to run frequently, which causes system lag.

Screening direction

Prioritize where loops or frequent calls are made.

Optimization scheme

Avoid creating large, temporary small objects.

Memory leaks

Memory leaks

In the case of Java, an Object stored in the heap cannot be properly collected by the GC

Causes of memory leaks

Long-life objects hold strong/soft references to short-life objects, causing short-life objects that should be recycled to fail to be recycled properly

Memory release

  • The object is assigned a null value and has not been called since.
  • Assigning new values to objects reallocates memory space.

Impact of memory leaks

  • The application has less memory available, increasing the pressure on heap memory
  • Reduced application performance, such as triggering more frequent GC
  • In serious cases, memory overflow errors, known as OOM errors, may result

Common memory leaks and solutions

Static properties cause memory leaks

The problem: One situation that can lead to memory leaks is the heavy use of static static variables. In Java, the life cycle of a static property usually accompanies the entire application life cycle (unless the ClassLoader meets the criteria for garbage collection).

Solutions:

  • Reduce static variables in;
  • If singletons are used, try to use lazy loading.
Collection classes

Problem: The collection element object is still referenced by the collection class after it has been added, making the collection element object unrecyclable and causing a memory leak

Solution: Collection elements added to a collection class must be removed from the collection after use

Unclosed resources

Problem: Whenever we create a connection or open a stream, the JVM allocates memory for these resources. For example, database links, input streams, and session objects. Forgetting to close these resources can clog up memory and prevent the GC from cleaning up. Especially when there is no resource closure in finally when an exception occurs in the program.

Solutions:

  • Always remember to close resources in finally;
  • Closing the connection’s own code cannot cause an exception;
  • Java7 and later can use try-with-resources code to close resources.
Improper implementation of equals and hashCode methods

Problem: When we define a new class, we often need to override equals and hashCode methods. Many operations in HashSet and HashMap use these two methods. If not overwritten properly, memory leaks can occur.

Solutions:

  • If you create an entity class, always override equals and hashCode;
  • Not only should the default method implementation be overridden, but the optimal implementation should also be considered;
The outer class references the inner class

Problem: This happens with non-static inner classes (anonymous classes), which always require an instance of the outer class when the class is initialized. By default, every non-static inner class holds an implicit reference to an external class. If an object of this inner class is used in an application, it is not garbage collected even after the outer class has been used.

Workaround: If an inner class does not need access to the member information of an outer class, consider turning it into a static inner class.

The finalize () method

Problem: There is a potential memory leak problem when using finalize() methods. Whenever a Finalize () method of a class is overridden, the objects of that class are not immediately collected by GC. The GC will queue them for finalization and reclaim them at a later point in time. If the Finalize () method overrides improperly or the Finalizer queue cannot keep up with the Java garbage collector, sooner or later, your application will get an OutOfMemoryError.

The solution: Always avoid finalizers.

String intern method

Problem: the string constant pool was moved from PermGen to heap space in Java7. In Java6 and earlier, we had to be careful with strings. If you read a large String object and call its intern method, intern() puts the String into the JVM’s PermGen, which is not GC. It also causes application performance degradation and memory overflow problems.

Solutions:

  • The easiest way to do this is to update the JDK version to 7 or later;
  • If this is unavoidable, adjust the PermGen size to avoid OutOfMemoryErrors overflows.
Using ThreadLocal

Problem: ThreadLocal provides thread-local variables that are guaranteed to belong to the current thread. Each thread holds a copy of the variable, and each thread has a different variable. ThreadLocal provides thread isolation by binding variables to threads, thereby implementing thread-safe features.

In the implementation of ThreadLocal, each Thread maintains a ThreadLocalMap. The key is the ThreadLocal instance itself, and the value is the Object that needs to be stored.

A ThreadLocalMap uses a weak reference to a ThreadLocal as its key. If a ThreadLocal has no external strong reference to it, then the ThreadLocal will be reclaimed during GC. Null key entries appear in ThreadLocalMap, and there is no way to access the values of these null key entries.

If the current Thread does not terminate, there will always be a strong reference chain for the values of these entries with null keys: Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value can never be reclaimed, resulting in a memory leak.

Solutions:

  • Use the remove method provided by ThreadLocal to remove a value from the current thread.
  • Instead of using threadlocal.set (null) to clear the value, it does not actually clear the value, but looks up the Map associated with the current thread and sets the key-value pair to the current thread and NULL, respectively.
  • It is best to think of ThreadLocal as a resource that needs to be closed ina finally block to ensure that it is always closed even in the event of an exception.
conclusion

Out of memory

Out of memory

A memory overflow error occurs when a program runs on more memory than is available. Memory leaks are one of the possible causes of an overflow

Cause Of memory overflow

There is too much memory in the system that can’t be reclaimed, or too much memory is used, and eventually the program runs larger than the maximum memory that can be provided, or it can be understood that leakage is the process and overflow is the result

Impact of memory overflow

The program crashes, i.e. OOM Error

Common causes and solutions of memory overflow

Overflow reason
  • The data loaded in memory is too large, for example, multiple data are fetched from the database at a time;
  • There are references to objects in the collection class, which are not emptied after use, making it impossible for the JVM to recycle;
  • An infinite loop or loop that produces too many duplicate object entities in code;
  • Bugs in using third-party software;
  • The memory Settings are too small. Procedure
The solution
  • Modify memory to directly add memory
  • Check the error log to see if there are other errors in OOM.
  • Walk through and analyze the code
  • Use the memory viewer tool to dynamically check memory usage

Memory analysis tool

Even if the cause of memory leaks is fully understood, memory leaks will inevitably occur. The following describes the analysis tools for memory leaks

Specific tools

  • Android Studio Monitor
  • MAT(Memory Analysis Tools) for Eclipse: www.eclipse.org/mat/
  • YourKit:www.yourkit.com/

Open source library

  • LeakCanary (From Square)
  • BlockCanary

Memory optimized space

Unnecessary automatic boxing

Automatic boxing is the conversion of basic data types to corresponding complex types. Automatic boxing is full of problems in HashMap addition, deletion, change and query, so try to avoid this problem. For example, replace HashMap with SparseArray and ArrayMap

A memory multiplexing

Resource reuse: universal string, color, layout view reuse: similar to RecyclerView optimization reuse object pool: create object pool, do not need to create objects repeatedly, similar to thread pool, Messae share metadata mode Bitmap object reuse: Using the inBitmap attribute tells the Bitmap decoder to try to use an existing memory area, and the newly decoded Bitmap will try to use the pixel data memory area occupied by the previous Bitmap in the heap.

Release the memory when the available memory of App is too low. Rewrite the onTrimMemory/onLowMemory method in Application to release the image cache and static cache when the App is about to be killed due to memory constraint.

Optimization of other scenarios

Removes references to images when item is not visible

ListView: So every time an item is reclaimed and reused, it rebinds the data, simply by releasing the image reference in ImageView onDetachFromWindow. RecyclerView: Because the first choice when the recycled item is invisible is to put it into mCacheView, the reuse of the item does not require only bindViewHolder to rebind the data, but only after it is recycled into the mRecyclePool and taken out for reuse. So rewrite the recycler. Adapter onViewRecycled() method to release items when they are recycled into RecyclePool.

If string concatenation is used, use StringBuilder, StringBuffer custom Views to reduce onDraw time and execution times use static inner classes use base data types and soft/weak references when appropriate

Online monitoring mode

  1. Routine surveillance

    1. If the memory usage exceeds 80%, run debug. dumpHprofData(String fileName) to obtain the dump file and send it to the server, and then manually analyze the file
    2. LeakCanary integrates and brings it online
  2. Probe Online monitoring tool

  3. LeakInspector

  4. ResourceCanary

Memory-related basics

An introduction to the four reference types

  • StrongReference: the JVM would rather throw an OOM than have the GC reclaim an object with a StrongReference;
  • SoftReference: an object returned only when the memory space is insufficient.
  • WeakReference: in GC, once an object with only WeakReference is found, its memory will be reclaimed no matter whether the current memory space is sufficient or not.
  • PhantomReference: can be collected by the GC at any time. When the garbage collector is about to reclaim an object and finds that it has a PhantomReference, it adds the PhantomReference to its associated reference queue before reclaiming the object’s memory. A program can determine whether an object is about to be reclaimed by determining whether a virtual reference to the object exists in the reference queue. Can be used as a flag for GC to reclaim an Object.

JVM Memory Management

Please refer to: www.jianshu.com/p/26f7f597c…