What is OOM? How to solve OOM problem!

1. What is OOM?

The program requested too much memory, the virtual machine could not satisfy us, and then committed suicide. This phenomenon usually occurs in the development of APP with large pictures, or when a lot of pictures need to be used. Generally speaking, when our APP needs to apply for a piece of memory to store pictures, the system thinks that our program needs too much memory, even if the system has sufficient memory, such as 1G, but the system will not allocate it to our APP, so Throwing an OOM exception, the program did not catch the exception, so the pop-up window crashed

2. Why is there OOM?

Because the APP of the Android system has a maximum memory limit per process or virtual machine, once the limit is exceeded, the system will throw an OOM error. It has nothing to do with whether the remaining memory of the phone is sufficient.

3. Why does Android have APP memory limitations?

(1) It is more reasonable for developers to use memory. Limit the upper limit of available memory for each application to avoid malicious programs or a single program that uses too much memory to cause other programs to become inoperable. With restrictions, developers must use resources reasonably and optimize resource use

(2) The content displayed on the screen is limited and the memory is sufficient . Even if there are thousands of pictures and tens of millions of data that need to be used, what needs to be displayed to users at a specific moment is always limited, because the screen display is so large, and the information that can be placed on it is very limited. Most of the information is ready to display, so there is no need to give too much heap memory. There must be a ListView to display pictures. For example, this ListView contains 500 items, but the screen display has a maximum of 10 items displayed, and the rest of the data is in the state of being ready to display.

(3) The limitation of Android multiple virtual machines Davlik is required. The APP on the android device runs, and each time an application is opened, at least one independent virtual machine is opened. This avoids system crashes at the cost of wasting more memory.

4. There is GC to automatically recycle resources, why is there still OOM?

Android's GC will recycle unused resources according to a specific algorithm, but GC generally recycles unowned object memory or soft reference resources.

The use of soft-referenced image resources can avoid OOM to a certain extent.

ps: It is a good practice to set unused objects to null. But a better way is to recycle the unused images directly. Because sometimes it is too late for gc to recycle by setting null.

5. How to avoid OOM?

Manage image resources simply by SoftReference

Build a SoftReference hashmap. When using an image, first check whether the hashmap has s oftreference, and whether the image of s oftreference is empty. If it is empty, load the image into s oftreference and add the haspmap.

code show as below:

import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.widget.ImageView;


/**
 * Function description: load pictures asynchronously
 *
 */

public class AsyncImageLoaderCore {
    public Context context; // Will be used when doing local caching
    public HashMap<String, SoftReference<Bitmap>> imageCache;// 软引用集合
   
    public AsyncImageLoaderCore(Context context) {
        this.context = context;
        this.imageCache = new HashMap<String, SoftReference<Bitmap>>();
    }


    public Bitmap loadBitmap(final String imageUrl, final ImageView imageView, final ImageCallback imageCallback) {
        if (imageCache.containsKey(imageUrl)) {
            SoftReference<Bitmap> softReference = imageCache.get(imageUrl);
            if (softReference.get() != null)
                return softReference.get();
        }
        
        final Handler handler = new Handler(new Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                imageCallback.imageLoaded((Bitmap) msg.obj, imageView, imageUrl);
                return false;
            }
        });
        
        new Thread() {
            @Override
            public void run() {
                Bitmap bitmap = null;
                try {
                    bitmap = getHttpBitmap(imageUrl);
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }
                
                if (null != bitmap) {
                    imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
                    handler.sendMessage(handler.obtainMessage(0, bitmap));
                }
            }
        }.start();
        return null;
    }
    private final int MAX_PIC_LENGTH = 200000;// 最大字节长度限制[可调,最好不要超过200000]
    private final int SAMPLE_SIZE = 14;// 裁剪图片比列(1/14)[可调]
    /**
     * 获取网络图片
     */
    private Bitmap getHttpBitmap(String imgUrl) throws Exception {
        URL htmlUrl = new URL(imgUrl);
        URLConnection connection = htmlUrl.openConnection();
        HttpURLConnection conn = (HttpURLConnection) connection;
        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
            InputStream inputStream = conn.getInputStream();
            byte[] bytes = changeToBytes(inputStream);
            if (bytes.length < MAX_PIC_LENGTH) {
                return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            } else if (bytes.length < MAX_PIC_LENGTH * SAMPLE_SIZE) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = false;
                options.inSampleSize = SAMPLE_SIZE;
                return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
            }
        }
        return null;
    }


    /**
     * 将流转换成字节数组
     */

    public byte[] changeToBytes(InputStream inputStream) throws Exception
    {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];// 每次读取的字节长度
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1)
        {
            outputStream.write(buffer, 0, len);
        }
        inputStream.close();
        return outputStream.toByteArray();
    }
    /**
     * 异步加载资源回调接口
     */
    public interface ImageCallback {
        public void imageLoaded(Bitmap bitmap, ImageView imageView, String imageUrl);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325218012&siteId=291194637