项目场景:
同事在开发一款人脸识别app时,在多次执行,打开--》人脸识别--》关闭--》打开循环测试过程中会耗尽内存导致被kill。
问题描述:
测试同学通过用monkey脚本测试,遇到内存泄漏的问题。
-
日志片段1:可以看到系统一直在频繁gc,已经超过设定的512mb上限。
09-22 13:53:21.106 3052 3127 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:21.630 3052 5107 I zygote : Clamp target GC heap from 535MB to 512MB
09-22 13:53:21.630 3052 5107 I zygote : Alloc concurrent copying GC freed 38(1192B) AllocSpace objects, 0(0B) LOS objects, 0% free, 511MB/512MB, paused 167us total 1.441s
09-22 13:53:21.630 3052 3142 I zygote : WaitForGcToComplete blocked Alloc on HeapTrim for 2.013s
09-22 13:53:21.630 3052 5107 W zygote : Throwing OutOfMemoryError "Failed to allocate a 460812 byte allocation with 1192 free bytes and 1192B until OOM, max allowed footprint 536870912, growth limit 536870912"
09-22 13:53:21.630 3052 3142 I zygote : Starting a blocking GC Alloc
09-22 13:53:21.630 3052 3142 I zygote : Starting a blocking GC Alloc
09-22 13:53:21.630 3052 4168 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:21.630 3052 5107 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:21.630 3052 3806 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:21.630 3052 3127 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:21.630 3052 3061 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.103 3052 3142 I zygote : Clamp target GC heap from 535MB to 512MB
09-22 13:53:22.103 3052 3142 I zygote : Alloc concurrent copying GC freed 30(808B) AllocSpace objects, 0(0B) LOS objects, 0% free, 511MB/512MB, paused 145us total 472.588ms
09-22 13:53:22.103 3052 4168 I zygote : WaitForGcToComplete blocked Alloc on HeapTrim for 2.484s
09-22 13:53:22.103 3052 4168 I zygote : Starting a blocking GC Alloc
09-22 13:53:22.103 3052 4168 I zygote : Starting a blocking GC Alloc
09-22 13:53:22.103 3052 3142 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.103 3052 3127 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.103 3052 3061 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.103 3052 3806 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.103 3052 5107 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.557 3052 4168 I zygote : Clamp target GC heap from 535MB to 512MB
09-22 13:53:22.557 3052 4168 I zygote : Alloc concurrent copying GC freed 0(0B) AllocSpace objects, 0(0B) LOS objects, 0% free, 511MB/512MB, paused 131us total 453.636ms
09-22 13:53:22.557 3052 3127 I zygote : WaitForGcToComplete blocked Alloc on HeapTrim for 1.451s
09-22 13:53:22.557 3052 3127 I zygote : Starting a blocking GC Alloc
09-22 13:53:22.557 3052 3142 I zygote : WaitForGcToComplete blocked Alloc on HeapTrim for 454.347ms
09-22 13:53:22.558 3052 3142 I zygote : Starting a blocking GC Alloc
09-22 13:53:22.558 3052 3061 I zygote : WaitForGcToComplete blocked Alloc on HeapTrim for 2.941s
09-22 13:53:22.558 3052 3061 I zygote : Starting a blocking GC Alloc
09-22 13:53:22.558 3052 3061 I zygote : Starting a blocking GC Alloc
09-22 13:53:22.558 3052 3806 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.558 3052 5107 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.558 3052 4168 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.558 3052 3142 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:22.558 3052 3127 I zygote : Waiting for a blocking GC Alloc
09-22 13:53:23.032 3052 3061 I zygote : Clamp target GC heap from 535MB to 512MB
09-22 13:53:23.032 3052 3061 I zygote : Alloc concurrent copying GC freed 23(552B) AllocSpace objects, 0(0B) LOS objects, 0% free, 511MB/512MB, paused 120us total 474.598ms
09-22 13:53:23.033 3052 3806 I zygote : WaitForGcToComplete blocked Alloc on HeapTrim for 2.804s
09-22 13:53:23.033 3052 3806 I zygote : Starting a blocking GC Alloc
-
日志片段2:已经无法再分配新的内存空间
09-22 13:53:30.408 3052 3142 W System.err: java.lang.RuntimeException: Exception while computing database live data.
09-22 13:53:30.409 3052 3142 W System.err: at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
09-22 13:53:30.409 3052 3142 W System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
09-22 13:53:30.409 3052 3142 W System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
09-22 13:53:30.409 3052 3142 W System.err: at java.lang.Thread.run(Thread.java:764)
09-22 13:53:30.409 3052 3142 W System.err: Caused by: android.database.sqlite.SQLiteException: unknown error (code 0): Native could not create new byte[]
09-22 13:53:30.409 3052 3142 W System.err: at android.database.CursorWindow.nativeGetBlob(Native Method)
09-22 13:53:30.410 3052 3142 W System.err: at android.database.CursorWindow.getBlob(CursorWindow.java:403)
09-22 13:53:30.410 3052 3142 W System.err: at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:45)
09-22 13:53:30.410 3052 3142 W System.err: at com.decard.facediscernoffline.module_base_offline.bean.db.FaceDataDao_Impl$10.call(FaceDataDao_Impl.java:1032)
09-22 13:53:30.410 3052 3142 W System.err: at com.decard.facediscernoffline.module_base_offline.bean.db.FaceDataDao_Impl$10.call(FaceDataDao_Impl.java:1016)
09-22 13:53:30.410 3052 3142 W System.err: at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
09-22 13:53:30.410 3052 3142 W System.err: ... 3 more
原因分析:
-
1,查询此设备的DVM分配的heap上限
adb shell getprop | grep heap
[dalvik.vm.heapsize]: [512m]
-
2,重复复现步骤,抓取内存申请快照hprof文件
adb shell am dumpheap com.xxx.xxx /data/local/tmp/14_54.hprof
hprof-conv 14_54.hprof 14_54_R.hprof
hprof-conv在sdk的platform-tools目录中
-
3,使用Memory Analyzer Tool进行分析
打开14_54_R.hprof 文件后,
竟然有多个activity实例,基本断定是发生了上下文的强引用导致Activity无法被回收。
-
4,点击右键Paths to GC Roots-->exclude all phantom/weak/soft etc reference
发现引用的代码位置,进行排查,发现使用的都是activity的context。
解决方案:
重构代码,把需要引用上下文对象的类,都用ApplicationContext 来代替。