记一次内存泄漏问题排查
Posted alexkn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次内存泄漏问题排查相关的知识,希望对你有一定的参考价值。
通过MonitoSDK的Sample App进行试用时,发现存在部分内存泄漏的情况,leakcanary直接弹出提示如下
可以看到MonitorDBActivity的instance导致泄漏。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_db); ButterKnife.bind(this); } @OnClick(R.id.inputData) public void inputData() { EditText input = (EditText) findViewById(R.id.inputTestData); int num = Integer.valueOf(input.getEditableText().toString()); ErrorReporter reporter = ACRA.getErrorReporter(); CrashReportDataFactory factory = null; try { factory = Reflect.on(reporter).get("crashReportDataFactory"); } catch (ReflectException e) { e.printStackTrace(); } for (int i = 0; i < num; i++) { final ReportBuilder builder = new ReportBuilder(); builder.exception(new Exception(i + "")); final CrashReportData crashReportData = factory.createCrashData(builder); MLog log = null; try { log = new MLog(crashReportData.toJSON().toString()); } catch (JSONReportBuilder.JSONReportException e) { e.printStackTrace(); } MLogStoreMgr.getInstance(this).add(log); } }
可以看到,log相关操作只有MLogStoreMgr.getInstance(this).add(log);这一行代码,继续debug,可以看到最后底层执行的是
if(!UploadTask.isRunning()) { TaskExecutor.getInstance().postDelayed(1, new UploadTask() { public void onUploadExcuted() { if(UploadEngine.this.bRunning) { UploadEngine.this.calNextInterval(); if(TaskExecutor.getInstance().hasCallbacks(1)) { TaskExecutor.getInstance().removeCallbacks(1); } if(!UploadTask.isRunning()) { TaskExecutor.getInstance().postDelayed(1, this, UploadEngine.this.mPeriod); } } } public void deleteError() { } }, this.mPeriod); }
没错,就是这个postDelayed导致的。这可是在主线程执行的。因此因为这个方法,导致主线程MainActivity的引用无法被释放,直到消息被looper处理掉。因此,做了如下改造。
以上是关于记一次内存泄漏问题排查的主要内容,如果未能解决你的问题,请参考以下文章