1. 程式人生 > >記一次內存泄漏問題排查

記一次內存泄漏問題排查

set mage let tac rtb repo int exc adt

通過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處理掉。因此,做了如下改造。

技術分享圖片

記一次內存泄漏問題排查