Summary of Android methods to avoid memory overflow (Out of Memory)

Summary of Android methods to avoid memory overflow (Out of Memory)

The method to avoid memory overflow is mainly to optimize the program in the following three aspects

Memory references

Before dealing with memory references, let's review what strong references, soft references, weak references, and phantom references are.

Strong reference: Strong reference is the most commonly used reference. If an object has a strong reference, the garbage collector will never recycle it. When the memory space is insufficient, the Java virtual machine would rather throw an OutOfMemoryError error and cause the program to terminate abnormally than solve the problem of insufficient memory by randomly recycling objects with strong references.

Soft reference: If an object has only soft references, but there is enough memory space, the garbage collector will not recycle it; it will not be reclaimed until the virtual machine reports that there is not enough memory. As long as the garbage collector does not recycle it, the object can be used by the program. Soft references can be used to implement memory-sensitive caches. Soft references can be used in conjunction with a reference queue (ReferenceQueue). If the object referenced by the soft reference is reclaimed by the garbage collector, the Java virtual machine will add the soft reference to the reference queue associated with it.

Weak reference: Objects with only weak references have a shorter life cycle. When the garbage collector thread scans the memory area under its jurisdiction, once an object with only weak references is found, its memory will be reclaimed regardless of whether the current memory space is sufficient. However, since the garbage collector is a very low priority thread, it may not find objects with only weak references quickly. Weak references can be used in conjunction with a reference queue (ReferenceQueue). If the object referenced by the weak reference is garbage collected, the Java virtual machine will add the weak reference to the reference queue associated with it.

Phantom reference: Phantom reference can be understood as a virtual reference. Unlike other references, phantom reference does not determine the life cycle of an object. If an object only holds phantom references, it is like having no references and may be reclaimed by the garbage collector at any time. Phantom references are mainly used to track the activities of objects being reclaimed by the garbage collector. One difference between phantom references and soft references and weak references is that phantom references must be used in conjunction with a reference queue (ReferenceQueue). When the garbage collector is about to reclaim an object, if it finds that it still has phantom references, it will add this phantom reference to the reference queue associated with it before reclaiming the object's memory. The program can determine whether the referenced object is about to be garbage collected by judging whether a phantom reference has been added to the reference queue. If the program finds that a phantom reference has been added to the reference queue, it can take necessary actions before the memory of the referenced object is reclaimed.

1. Release strong references

Generally, when we declare object variables, we ignore them after use, thinking that the garbage collector will help us recycle the memory space pointed to by these objects. In fact, if the memory space of this object is still in a referenced state, the garbage collector will never recycle its memory space. Only when this memory space is not referenced by any object will the garbage collector recycle it.

So after we finish using the object, we can set the object to null, so that my garbage collector GC will release the memory space allocated for the object at the appropriate time.

  1. Object obj = new Object();
  2. obj = null ;

Of course, before setting it to ***, you must confirm whether you no longer need to use the object. If you need to use this object at any time, you cannot do this.

2. Use soft references

Before the JVM reports insufficient memory, all soft references will be cleared. In this way, the GC can collect a lot of memory space released by soft references, thereby solving the problem of tight memory and avoiding memory overflow. When it is recycled depends on the GC algorithm and the amount of memory available when the GC is running.

We can use SoftReference to encapsulate strongly referenced objects

  1. String str = "zhuwentao" ; // strong reference
  2.  
  3. SoftReference<String> strSoft = new SoftReference<String>(str); // Use soft reference to encapsulate strong reference

3. Use weak references

The execution process of gc collecting weak reference objects is the same as soft references, except that gc does not decide whether to recycle weak reference objects based on memory conditions.

  1. String str = "zhuwentao" ; // strong reference
  2. WeakReference<String> strWeak = new WeakReference<String>(str); // Use weak references to encapsulate strong references

If you want to be able to obtain information about an object at any time, but do not want to affect the garbage collection of the object, you should use WeakReference to remember the object instead of using a general Reference.

Image Processing

Most OOMs occur when loading images. When loading large images, we need to pay special attention to avoid OOMs.

When processing large images, no matter how much memory your phone has, if you do not process the images, memory overflow may occur.

Because the Android system allocates a certain amount of memory for each application and does not allocate the entire system memory to the application, no matter how much memory your phone has, the memory that each App can use is limited.

This is very different from the PC side. If the PC side does not have enough memory, you can request to use virtual memory, but the Android system does not have this mechanism.

1. Compress images in memory

When loading large images, you need to compress the images. Use proportional compression to process the images directly in memory.

  1. Options options = new BitmapFactory.Options();
  2. options.inSampleSize = 5; // One fifth of the original image, set to 2 for half
  3. BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);

When doing this, please note that the image quality will deteriorate. The larger the value of inSampleSize is set, the worse the image quality will be. Different mobile phone manufacturers may have different scaling ratios.

2. Reclaim the memory occupied by the image after using it

Since the outer layer of Android uses Java and the underlying layer uses C language, the memory space allocated for the image object in the inner layer.

So although our external layer seems to be released, the inner layer is not necessarily completely released. We will release the inner layer's memory space only after we have finished using the image.

  1. if (!bitmapObject.isRecyled()) { // The Bitmap object has not been recycled
  2. bitmapObject.recycle(); // Release
  3. System.gc(); // Remind the system to recycle in time
  4. }

3. Reduce the color quality of the picture to be displayed

There are four image color modes for Bitmap in Android:

ALPHA_8: Each pixel takes up 1 byte of memory

RGB_565: Each pixel takes up 2 bytes in memory

ARGB_4444: Each pixel takes up 2 bytes in memory

ARGB_8888: Each pixel takes up 4 bytes in memory

When we create a Bitmap, the default color mode is ARGB_8888, which has the highest quality, but of course it also takes up the most memory.

Each pixel of ARGB_4444 only occupies 2 bytes, so using the ARGB_4444 mode can also reduce the memory size occupied by the image.

  1. BitmapFactory.Options options = new BitmapFactory.Options();
  2. options.inPreferredConfig = Bitmap.Config.ARGB_4444;
  3. Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), o

In fact, after most images are set to ARGB_4444 mode, there is no visible difference in display compared to ARGB_8888 mode. It is just that for images with gradient color effects, the gradient may show a color strip effect.

This method of reducing color quality does not reduce memory usage as much as method 1.

4. Do not load the image into memory when querying image information

Sometimes we get a picture, maybe just to get some information about the picture, such as the width, height and other information of the picture, which does not need to be displayed on the interface. At this time, we can choose not to load the picture into memory.

  1. BitmapFactory.Options options = new BitmapFactory.Options();
  2.  
  3. options.inJustDecodeBounds = true ; // Do not load the image into memory
  4.  
  5. Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);

The inJustDecodeBounds property, if the value is true, will not return the actual Bitmap object, nor will it allocate memory space for it, but it allows us to query basic information such as image width, height, and size.

(Get the original width and height: options.outWidth, options.outHeight)

VMRuntime

VMRuntime is a class provided in the Android SDK.

It is only useful before Android 2.3. SDKs after 2.3 do not support it, so this VMRuntime is not universal.

A brief introduction will suffice here.

1. Optimize the heap memory allocation of Dalvik virtual machine

The setTargetHeapUtilization method provided by the VMRuntime class can enhance the processing efficiency of program heap memory.

  1. private final static   float TARGET_HEAP_UTILIZATION = 0.75f;
  2. VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);

2. Customize the heap memory size

Forcefully define the memory size that Android allocates to the current App, and use VMRuntime to set the minimum heap memory of the application.

  1. // Set the minimum heap memory size to 6MB
  2. private final static   int HEAP_SIZE = 6 * 1024 * 1024;
  3. VMRuntime.getRuntime().setMinimumHeapSize(HEAP_SIZE);

largeHeap

Let the Dalvik virtual machine allocate more memory for the App. This method can gain more memory space for our App, thereby alleviating the pressure of insufficient memory.

You can use the ActivityManager.getMemoryClass() method in the program to obtain the size of the App memory under normal usage, and use ActivityManager.getLargeMemoryClass() to obtain the maximum memory size when largeHeap is turned on.

1. Usage

This method is very simple to use. Just add "android:largeHeap="true" to the <application> node attribute in the AndroidManifest.xml file.

  1. <application
  2. android:icon= "@mipmap/ic_launcher"  
  3. android:label= "@string/app_name"  
  4. android:theme= "@style/AppTheme"  
  5. android:largeHeap= "true" >

2. Note

The memory that Dalvik adds to our App is probably obtained by killing other background processes. This is not a moral practice for a developer.

We should not rely on obtaining maximum memory to solve the OOM problem, but should avoid the OOM problem as much as possible through reasonable code writing.

<<:  Decryption - The mysterious RunLoop

>>:  Young man, it’s time to create your first cool 3D effect!

Recommend

Blind box event marketing is a blast!

Blind boxes have now become a new type of marketi...

How to calculate keyword conversion rate in Baidu bidding?

1. Conversion rate = number of orders/number of c...

10 PPT slides and 5 steps to teach you how to write first-class copy!

How to write first-class copy ? This has always b...

6,000 worms in one snail! What kind of snail can eat so much?

Audit expert: Li Weiyang Well-known science write...

A practical guide to user growth

User growth is no longer a new concept. Many comp...

Is it reliable to take Western medicine while drinking Chinese medicine?

This is the 4648th article of Da Yi Xiao Hu When ...

Keeping with the Milky Way

Author | Ignasi Ribas (Spain) Translation | Jiang...