Android应用内存泄漏与分析

本文就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 非常棒,定有收获。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值