Possible error in dalvik Android 2.x during Bitmap allocation?

The phenomenon . First, allocate some large blocks of memory on the Java side until we select OutOfMemoryError, and then free them all . Now strange things happen: load even a small image (for example, width: 200, height: 200) by BitmapFactory.decodeXXX (decodeResource, decodeFile, ...) will throw OutOfMemoryError! But its OK to allocate any pure Java large object (for example, a new byte [2 * 1024 * 1024]) now!

Verification I wrote some simple codes to check the problem, which can be downloaded here , click "Alloc" and you will get an OOF error, then click "Free All", now the environment is configured. Now you can click "LoadBitmap" and you will see that it does not work on most Android 2.x phones (but in the emulator it is just normal, odd)

Digging deeper . I'm trying to delve into some dalwick code to find out why and find a possible error in the externalAllocPossible function in HeapSource.c , which is called by dvmTrackExternalAllocation, which prints the message "big byte byte byte bytes for this process" in LogCat.

In externalAllocPossible, he simply wrote:

if (currentHeapSize + hs->externalBytesAllocated + n <= heap->absoluteMaxSize) { return true; } return false; 

This means that once, if the native size of the Bitmap allocation plus currentHeapSize ( NOT the actually allocated size , as shown below, in this case it preserves the maximum heap size that we hit but then freed them all) exceeds the limits, the native bitmap distribution is always will fail , but currentHeapSize in Java seems NOT to decrease even when the memory of Java objects has been freed up from 91.3% (set to null and trigger GC)!

enter image description here

Has anyone else encountered this problem?

0
source share
2 answers

I think that is correct. Forcing the entire application (Java + native) takes no more than a certain amount of memory from the OS. To do this, he must use the current heap size, since this amount of memory is still allocated for the application (it does not return to the OS when the GC is released, it only returns to the application memory pool).

In any case, 2.x is long dead, so they are not going to fix it. They have changed how bitmaps retain their memory in 3.x and 4.x. Itโ€™s best to select all the bitmaps you use, and then select these large structures. Or even better - drop these large structures into LRUCache of a fixed size and don't use the idea of โ€‹โ€‹growing to obscure memory, instead load new data only when necessary.

0
source

The Bitmap class has a recycle () method, which is described as:

Free your own object associated with this bitmap ...

The reason for this method is that there are two heaps: the Java heap and the heap used by native code. GC only sees Java heap sizes; for GC, a bitmap might look like a small object because its size on the Java heap is small, despite the fact that it refers to a large block of memory in the native heap.

0
source

Source: https://habr.com/ru/post/1499695/


All Articles