您的位置:首页 > 移动开发 > Android开发

Android应用内存泄漏与分析

2015-07-20 17:00 676 查看
本文就android内存泄漏种类,典型的泄漏区域,和怎么分析,以及配合一些例子进行分析

android内存泄露种类有

1)Native leak  ----- Global Reference(GREF) overflow

2)  Java heap leak 

2.1) java.lang.OutOfMemoryError

2.2) java.lang.OutOfMemoryError: bitmap size exceeds VM budget

GREF overflow长什么样呢?http://stackoverflow.com/questions/19070209/how-to-safely-write-to-gui-from-different-thread-in-xamarin-android里面就有这个例子,当》2000时就会发生Native Crash

09-28 18:09:39.231 D/dalvikvm( 731): GREF has increased to 1701
09-28 18:09:39.461 D/dalvikvm( 731): GREF has increased to 1801
09-28 18:09:40.192 D/dalvikvm( 731): GREF has increased to 1901
09-28 18:09:40.271 D/dalvikvm( 731): GC_CONCURRENT freed 305K, 7% free 6175K/6599K, paused 3ms+5ms
09-28 18:09:40.531 D/dalvikvm( 731): <span style="color:#ff0000;">GREF has increased to 2001</span>
09-28 18:09:40.531 W/dalvikvm( 731): JNI global reference table (0x475fd0) dump:
09-28 18:09:40.531 W/dalvikvm( 731): Last 10 entries (of 2001):
09-28 18:09:40.531 W/dalvikvm( 731): 2000: 0x40fa4e90 java.lang.NoClassDefFoundError
09-28 18:09:40.541 W/dalvikvm( 731): 1999: 0x40fb2e78 mono.java.lang.RunnableImplementor
.
.
.
09-28 18:09:40.581 E/dalvikvm( 731): Excessive JNI global references (2001) //OOPS!
09-28 18:09:40.581 E/dalvikvm( 731): <span style="color:#ff0000;">VM aborting</span>
09-28 18:09:40.581 E/mono-rt ( 731): Stacktrace:
09-28 18:09:40.581 E/mono-rt ( 731):
09-28 18:09:40.592 E/mono-rt ( 731): at <unknown> <0xffffffff>
09-28 18:09:40.592 E/mono-rt ( 731): at (wrapper managed-to-native) object.wrapper_native_0x408027e9 (intptr,intptr) <IL 0x00026, 0xffffffff>
09-28 18:09:40.592 E/mono-rt ( 731): at Android.Runtime.JNIEnv.NewGlobalRef (intptr) [0x00000] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.8.2-branch/bdc709d1/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.cs:389有两个函数负责JNI的code
创建一个global reference: static jobject NewGlobalRef(JNIEnv* env, jobject jobj) ;

删除一个global reference: static void DeleteGlobalRef(JNIEnv* env, jobject jglobalRef) ;

大部分是忘记关闭资源导致,比如Cursor用完忘记关闭

Java Heap Leak:

adb shell getprop | grep dalvik.vm.heapsize  //这个参数表示单个进程可用的最大内存,当然如果有heapgrowthlimit数字,以heapgrowthlimit为准

类似这种可以得

dalvik.vm.heapgrowthlimit=64m // 单个应用可用最大内存

这表示单个应用限制在64m,如果应用dalvik堆栈超过这个数就会报OOM

一个process包含两部分内存,一是VM heap,另外是External,OOM发生都是dalvik cause GC的时候并不能收回占用的vm heap size

GC_CONCURRENT freed 535K, 52% free 2978K/6087K, external 1685K/2133K, paused 1ms+3ms

GC_FOR_MALLOC  freed 565K, 40% free 6993K/11591K, external 3742K/4937K, paused 69ms

free: Allocated GC Heap(6993K),Total GC Heap(11591K)external allocated3742K,external允许最大值4937K

然后这个link里面有详细的log和说明:http://stackoverflow.com/questions/14523949/google-maps-android-api-v2-supportmapfragment-memory-leak
http://stackoverflow.com/questions/24354452/gridview-out-of-memory-universal-image-loader
这个pdf里面有详细的介绍,我不在这里面说了:http://www.kandroid.org/board/data/board/conference/file_in_body/1/511th_kandroidconf_memory_and_performance.pdf

有个资源也列出来:https://github.com/snailee/kmemtracer-libs

典型的leak发生在Context leak和bitmap leak

大部分Context leak是因为一个长期激活的Reference使用了Activity的Context,应该使用跟Activity相同的生命周期的Reference才行。所以最好用application的Context来代替。

尽量避免使用静态内部类如果你不能控制它的生命周期,如果使用了,使用WeakRef到外部类的话就会出现Context leak

例子:
http://stackoverflow.com/questions/19061488/android-mapview-v2-context-issues-and-memory-leak http://stackoverflow.com/questions/3346080/android-references-to-a-context-and-memory-leaks http://stackoverflow.com/questions/987072/using-application-context-everywhere http://stackoverflow.com/questions/30372119/android-memory-leak-with-internal-classes(这个很可能就是Are you passing 
Context
/
Activity
 references
to that 
Thread
 or 
AsyncTask
?


怎么避免:http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html(需翻墙)

Bitmap leak

在老的平台上常见

Bitmap是耗External,在native内存,

例子:http://stackoverflow.com/questions/5509268/java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget
http://stackoverflow.com/questions/11985497/android-java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget http://stackoverflow.com/questions/8286087/again-java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget
解决办法:http://developer.android.com/training/displaying-bitmaps/index.html

怎么分析(再次偷懒):

先抓到Hprof,然后用MAT分析,具体分析有个视频非常好,不过是Youtube上面的,需要翻墙,这里给出链接,https://www.youtube.com/watch?v=_CruQY55HOk 非常棒,定有收获。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息