UNCLE
OOM (Out Of Memory) is the Android application development, everyone believed that the problem encountered, and OOM stack trace in the crash log is generally no practical significance, because it is only when the memory allocation throws OOM exception, the reason stack trace and OOM this time has nothing to do. So locate and analyze multi-OOM issues will need to take some effort.
Now, I will combine an example, say something about how the positioning OOM problem.
problem
In the programmers finish the code, the basic flow test cleared, ready for release when the cloud test results is: a big wave OOM exception. I had no choice but to re-open the computer to locate the problem.
Because I am not a person to write code, so a direct look at the code a bit difficult to locate the problem, this time to get on the tool.
1. Qualitative issues
1.1 locate the problem, qualitative
This is OOM lead to a memory leak, or the application itself is poorly designed, leading to excessive memory to be loaded once, resulting in the OOM?
Method of locating the problem is very simple, look at the memory is not always growing, if memory has been growing in the use of the process, it is likely due to a memory leak.
1.2 Recommended Tools
Android Studio comes with a Memory Monitor, a very simple little tool, able to use memory in real time to show up, as simple as I think do not need to say more. As shown below:
After playing for a few minutes, I found several problems:
1. app just started when the memory footprint is very big, because with a lot of texture (poorly designed)
2. app after entering the player interface and launch, even if the operation does not do anything, the memory has been slow growth (memory leaks)
3. app I quit again into time, memory usage has nearly doubled (memory leaks)
Among them, the problem will soon be able to guess 2, after the player MediaPlayer
has not been released, after verifying the next, resolve.
2. Improper design? optimization!
This problem is very extensive, and for example, a solid color background images would not be achieved without exceeding the pixel values of the picture needs, the picture is not loaded beyond the display range, and so on.
Eventually I found a few pictures, only 1280x720, given figure is 1920x1080. At the same time a simple realization LazyLoading picture. Question 1 basic improvise to get.
3. Memory leak?
If in the course of the memory curve it has been a rising trend, which is likely a memory leak.
3.1 Viewing information heap
Android SDK toolset to provide such a tool: Device Monitor. Use as follows:
1. Open Device Monitor Android
2. Select the process you want to debug
3. Click the button Update Heap
FIG substantially as follows:
We can see the basic stack, as well as an overview of the objects in the heap.
3.2 Leak View Activity
Many common memory leaks are due to be released Activity object can not caused, by the following adb command can quickly navigate to this question:
adb shell dumpsys meminfo <package_name>
The results obtained are as follows:
** MEMINFO in pid 9953 [com.google.android.gm] **
Pss Pss Shared Private Shared Private Heap Heap Heap
Total Clean Dirty Dirty Clean Clean Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------ ------
Native Heap 0 0 0 0 0 0 7800 7637(6) 126
Dalvik Heap 5110(3) 0 4136 4988(3) 0 0 9168 8958(6) 210
Dalvik Other 2850 0 2684 2772 0 0
Stack 36 0 8 36 0 0
Cursor 136 0 0 136 0 0
Ashmem 12 0 28 0 0 0
Other dev 380 0 24 376 0 4
.so mmap 5443(5) 1996 2584 2664(5) 5788 1996(5)
.apk mmap 235 32 0 0 1252 32
.ttf mmap 36 12 0 0 88 12
.dex mmap 3019(5) 2148 0 0 8936 2148(5)
Other mmap 107 0 8 8 324 68
Unknown 6994(4) 0 252 6992(4) 0 0
TOTAL 24358(1) 4188 9724 17972(2)16388 4260(2)16968 16595 336
Objects
Views: 426 ViewRootImpl: 3(8)
AppContexts: 6(7) Activities: 2(7)
Assets: 2 AssetManagers: 2
Local Binders: 64 Proxy Binders: 34
Death Recipients: 0
OpenSSL Sockets: 1
SQL
MEMORY_USED: 1739
PAGECACHE_OVERFLOW: 1164 MALLOC_SIZE: 62
Which ViewRootImpl, Activities, AppContexts number of very worthy of attention.
For other meanings of output, see the developer docs
3.3 取heap dump
After determining the basic memory leak, you need to locate specific objects which leak, good positioning of the relevant code, this time we can analyze the heap dump.
heap dump is a snapshot of heap memory, what it can be used to analyze specific memory in the end there.
First, we need to derive a Device Manager heap dump, shown in FIG.
Then converted to java dump, with the Eclipse Memory Analyzer Tool (MAT) were analyzed.
With platform-tools in the hprof-conv be converted:
hprof-conv heap-original.hprof heap-converted.hprof
After the conversion is complete, we can use the MAT to open the analysis.
4. Eclipse Memory Analyzer Tool (MAT)
When we open the dump with MAT, see the basic interface is as follows:
Here are a few concepts you need to know:
1. Shallow Heap & Retained Heap
- Shallow Heap的大小就是对象所占的内存空间,一般一个Object持有一个引用会需要32或者64bit的空间(取决于JVM)。
- 由于A对象持有B对象引用会导致B对象在GC中不会被销毁,所以由于被对象直接或者间接持有引用而不会被释放的对象的占用的内存总和,就是Retained Heap。
- 简单来说,Shallow heap就是对象占用的空间,Retained Heap就是假如对象被释放,连带能够释放出来的空间。
2. Dominator Tree
-
定义在这里。简单来说,Dominator Tree可以很好地观察Retained Heap大小。
- 通常,在dump中查看Histogram和dominator_tree就可以看出一些端倪,例如这个例子中,histogram图中,占用内存最多的是byte[]对象,通过
右键 -> List object
菜单,可以看到
基本上都是Bitmap对象,而且Bitmap有重复数据:
到这一步,可以继续追查是谁导致两份相同的数据不能得到释放,通过右键 -> Path to CG root
功能,可以追查到最终是被哪个对象持有导致不能被释放,结果如下:
到这里,问题基本就明白了:
DBHelper
是一个单例静态对象,这个对象会持有一个Context
对象,在代码中被当成Context
传入DBHelper
的是一个Activity
对象,所以这个Activity
不会被释放;当这个Activity
被销毁重建时,新的Activity
会重新加载ContentView,而老的Activity
所持有的整个View的树全部不会被释放,同时View持有的图片也不会被释放,导致内存不够。
At this point, the whole issue has basically been found, and tell us, in single cases it is best not to hold Context
the object, if demand requires, to see this design is reasonable, and prudent use of the time.
A common technique MAT
When analyzing memory footprint, you can usually see the most variety when occupancy Bitmap
objects, this time, if we can directly display this Bitmap
content, you'll find it a lot easier. Here is a method to view:
See answer here on stackoverflow
end
I refer to the whole process is basically the Google official documents Investigating Your RAM Usage , this document can be read next.
Well, the article written here is over, if you think the article is well written give a praise chant? If you think there need to be improved, please give me a message. Will be serious inquiry, insufficiently corrected. Thank you.
Android architects of the road is long, encourage each other with it!