Author: Lin Guanhong/The Ghost at my Fingertips

The Denver nuggets: https://juejin.cn/user/1785262612681997

Blog: http://www.cnblogs.com/linguanh/

Making: https://github.com/af913337456/

Tencent cloud column: https://cloud.tencent.com/developer/user/1148436/activities

Bonus points for answering these memory management interview questions.


Preface: Standing on the shoulders of giants, summarize this article.

Directory:

  • Java Runtime three computational memory functions
  • OOM: Why do big games need so much memory?
  • How to bypass dalviKVM heap size limit?
  • Is Bitmap allocated to native heap or Dalvik Heap?

The Java Runtime provides three computational memory functions:

MaxMemory Retrieves the maximum memory that the current APP can apply for, at the Java Heap level, similarly below.

TotalMemory takes the memory that the current APP has taken from the system, both in use and unused, and since applications typically require more than one portion, it is always taken from the system slowly as needed

FreeMemory retrieves memory held by the current APP, which is not yet used and can be recycled by GC.

Calculate the usedMemory used by the APP in the Java Heap layer at this point:


usedMemory = totalMemory - freeMemory

Copy the code

2. OOM: Why do large games require so much memory?

The evaluation of OOM is different in different Android versions.

  • In layman’s terms, an OOM is thrown when the current process’s total memory usage exceeds one limit.

  • Technically, Android sets a Dalvik Heap Size threshold for each process, which can vary on different devices due to the Size of RAM. If the APP wants to allocate more memory than this threshold, an OOM occurs.

  • Before Android 3.x, bitmaps were allocated in the Native heap, and after 3.x, bitmaps were allocated in the Java heap in Dalvik or ART.

  • In Android 2.x, an OOM will occur when Dalvik Allocated + native allocated + newly allocated size >= dalvik Heap maximum. Consider the per-process memory limit imposed by native Heap.

  • Android 3.x system, the abolition of native counters, bitmap-like allocation to dalvik’s Java Heap application, Allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory = allocated memory The Native heap is only limited by the total native memory (including RAM and SWAP or paging files).

Is this why some apps (such as large games) can exceed the Dalvik Heap Size value? That’s because Java memory is divided into Java Heap and Native Heap. After 3.x, Native Heap is not bound by this value. Memory like C/C++ is allocated in the Native Heap. In addition, bitmaps are allocated in the Java Heap, and we often encounter OOM caused by bitmaps during development, which is an example.

3. How to bypass dalviKVM heap size limit?

  • Create child process, as mentioned above, memory allocation by process. Then use process communication

By creating a new process, we can allocate some objects to the heap of the new process, thus achieving the goal of using more memory for an application. Of course, creating child processes adds overhead and is not suitable for all applications, depending on the need.

To create a child process: use the Android: Process tag

  • Using JNI to apply space on native Heap for different system versions (recommended)

3. The growth of the native heap of the post-X system is not limited by the Dalvik VM Heapsize. As long as there is free RAM space, the programmer can always apply for space on the Native heap. Sometimes when people use some software, there will be flash back, which may be caused by the software applying for more memory in the native layer. For example, I have encountered UC Web flash back when browsing a web page with a lot of content, because its native heap increased to a large value, occupied a lot of RAM, and was killed by memory killer.

  • Use video memory (part of the OPERATING system’s reserved RAM as video memory)

Texture Memory is not limited by dalvik VM Heapsize, using apis like OpenGL Textures, which I haven’t practiced. For example, Android GraphicBufferAllocator requests memory as video memory.

4. Is Bitmap allocated to native heap or Dalvik Heap?

Why is it in the Java heap and not in the Native heap for 3.x and later versions of different systems? Please see the source code below.

Main document

framework/base/graphic/java/Android/graphics/BitmapFactory.java  
framework/base/core/jni/Android/graphics/BitmapFactory.cpp  
framework/base/core/jni/Android/graphics/Graphics.cpp  
Copy the code

Bitmapfactory.java has several decode*** methods for creating bitmaps, which eventually call:


private staticnative Bitmap nativeDecodeStream(InputStream is, byte[] storage,Rect padding,Options opts);

Copy the code

NativeDecodeStream () calls the deDecode method in bitmapFactory.cpp, and eventually the createBitmap method in graphics.cpp.

CreateBitmap ();

jobjectGraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,  
                                  boolisMutable, jbyteArray ninepatch, int density)  
{  
    SkASSERT(bitmap);  
    SkASSERT(bitmap->pixelRef());  
   
    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,  
           static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)),  
            buffer, isMutable, ninepatch,density);  
    hasException(env); // For the side effectof logging.  
    return obj;  
}  
Copy the code

From the code you can see that the bitmap object is passed env->NewOject(…) JNIEnv’s NewOject method returns a Java object, not a native object, so it is allocated to the Dalvik Heap.