Android - BitmapFactory.decodeByteArray - OutOfMemoryError (OOM)

13,136

I have run into problems like this in the past. Android uses Bitmap VM and it is very small. Make sure you dispose your bitmap via bmp.recycle. Later versions of Android have more Bitmap VM but the version that I've been dealing with has a 20MB limit.

Share:
13,136
Bob Keathley
Author by

Bob Keathley

Updated on June 04, 2022

Comments

  • Bob Keathley
    Bob Keathley almost 2 years

    I have read 100s of article about the OOM problem. Most are in regard to large bitmaps. I am doing a mapping application where we download 256x256 weather overlay tiles. Most are totally transparent and very small. I just got a crash on a bitmap stream that was 442 Bytes long while calling BitmapFactory.decodeByteArray(....).

    The Exception states:

    java.lang.OutOfMemoryError: bitmap size exceeds VM budget(Heap Size=9415KB, Allocated=5192KB, Bitmap Size=23671KB)
    

    The code is:

    protected Bitmap retrieveImageData() throws IOException {
        URL url = new URL(imageUrl);
        InputStream in = null;
        OutputStream out = null;
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    
        // determine the image size and allocate a buffer
        int fileSize = connection.getContentLength();
        if (fileSize < 0) {
            return null;
        }
        byte[] imageData = new byte[fileSize];
    
        // download the file
        //Log.d(LOG_TAG, "fetching image " + imageUrl + " (" + fileSize + ")");
        BufferedInputStream istream = new BufferedInputStream(connection.getInputStream());
        int bytesRead = 0;
        int offset = 0;
        while (bytesRead != -1 && offset < fileSize) {
            bytesRead = istream.read(imageData, offset, fileSize - offset);
            offset += bytesRead;
        }
    
        // clean up
        istream.close();
        connection.disconnect();
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeByteArray(imageData, 0, bytesRead);
        } catch (OutOfMemoryError e) {
            Log.e("Map", "Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage());
            System.gc();
        }
        return bitmap;
    
    }
    

    Here is what I see in the debugger:

    bytesRead = 442
    

    So the Bitmap data is 442 Bytes. Why would it be trying to create a 23671KB Bitmap and running out of memory?