昨天有测试报告说这个版本的应用在重复跑测试case的时候内存不断变大
由于测试case会重复启动activity首先就怀疑是不是activitty导致的内存泄漏
Adb shell dumpsys meminfo [packagename]
通过dump 信息,发现activity的实例确实在不断变多,但查阅代码并未发现任何持有引用的地方
android studio profile来 dump内存信息发现最短的引用路径来自android os. ActivityThead
开始有点不信,不觉得系统的引用的会导致内存不断增加,然后再次使用MAT分析
发现确实来自ActivityThead.mNewActivities
源码分析
通关简单分析发现mNewActivities 是一个链表
搜索关键字发现仅仅只在ActivityThead.Idler这个私有类里进行了引用释放,这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
private class Idler implements MessageQueue.IdleHandler { @Override public final boolean queueIdle() { ActivityClientRecord a = mNewActivities; boolean stopProfiling = false; if (mBoundApplication != null && mProfiler.profileFd != null && mProfiler.autoStopProfiler) { stopProfiling = true; } if (a != null) { mNewActivities = null; IActivityTaskManager am = ActivityTaskManager.getService(); ActivityClientRecord prev; //此处循环对链表a进行了置空操作,用于打断引用链 do { if (localLOGV) Slog.v( TAG, "Reporting idle of " + a + " finished=" + (a.activity != null && a.activity.mFinished)); if (a.activity != null && !a.activity.mFinished) { try { am.activityIdle(a.token, a.createdConfig, stopProfiling); a.createdConfig = null; } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } prev = a; a = a.nextIdle; prev.nextIdle = null; } while (a != null); } if (stopProfiling) { mProfiler.stopProfiling(); } applyPendingProcessState(); return false; } } |
MessageQueue.IdleHandler 这是一个接口,查阅注释发现这个接口仅仅只有当前线程 MessageQueue 空闲之后才会回调